BotSharp/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs
2025-01-23 23:45:43 -06:00

74 lines
2.2 KiB
C#

using BotSharp.Abstraction.Infrastructures;
using Medallion.Threading.Redis;
using StackExchange.Redis;
namespace BotSharp.Core.Infrastructures;
public class DistributedLocker : IDistributedLocker
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public DistributedLocker(
IServiceProvider services,
ILogger<DistributedLocker> logger)
{
_services = services;
_logger = logger;
}
public async Task<bool> LockAsync(string resource, Func<Task> action, int timeoutInSeconds = 30)
{
var timeout = TimeSpan.FromSeconds(timeoutInSeconds);
var redis = _services.GetService<IConnectionMultiplexer>();
if (redis == null)
{
_logger.LogWarning($"The Redis server is experiencing issues and is not functioning as expected.");
await action();
return true;
}
var @lock = new RedisDistributedLock(resource, redis.GetDatabase());
await using (var handle = await @lock.TryAcquireAsync(timeout))
{
if (handle == null)
{
_logger.LogWarning($"Acquire lock for {resource} failed due to after {timeout}s timeout.");
return false;
}
await action();
return true;
}
}
public bool Lock(string resource, Action action, int timeoutInSeconds = 30)
{
var timeout = TimeSpan.FromSeconds(timeoutInSeconds);
var redis = _services.GetRequiredService<IConnectionMultiplexer>();
if (redis == null)
{
_logger.LogWarning($"The Redis server is experiencing issues and is not functioning as expected.");
action();
return false;
}
var @lock = new RedisDistributedLock(resource, redis.GetDatabase());
using (var handle = @lock.TryAcquire(timeout))
{
if (handle == null)
{
_logger.LogWarning($"Acquire lock for {resource} failed due to after {timeout}s timeout.");
return false;
}
else
{
action();
return true;
}
}
}
}