BotSharp/src/Infrastructure/BotSharp.Core/Infrastructures/DistributedLocker.cs

65 lines
2 KiB
C#
Raw Normal View History

2024-12-03 22:52:14 +00:00
using BotSharp.Abstraction.Infrastructures;
2024-07-15 21:38:47 +00:00
using Medallion.Threading.Redis;
2024-04-30 12:50:01 +00:00
using StackExchange.Redis;
namespace BotSharp.Core.Infrastructures;
2024-12-03 22:52:14 +00:00
public class DistributedLocker : IDistributedLocker
2024-04-30 12:50:01 +00:00
{
2025-01-02 22:48:28 +00:00
private readonly IServiceProvider _services;
2024-11-08 20:53:04 +00:00
private readonly ILogger _logger;
2024-04-30 12:50:01 +00:00
2025-01-02 22:48:28 +00:00
public DistributedLocker(IServiceProvider services, ILogger<DistributedLocker> logger)
2024-04-30 12:50:01 +00:00
{
2025-01-02 22:48:28 +00:00
_services = services;
2024-11-08 20:53:04 +00:00
_logger = logger;
2024-07-15 21:38:47 +00:00
}
2024-12-03 22:52:14 +00:00
public async Task<bool> LockAsync(string resource, Func<Task> action, int timeoutInSeconds = 30)
2024-07-15 21:38:47 +00:00
{
var timeout = TimeSpan.FromSeconds(timeoutInSeconds);
2024-04-30 12:50:01 +00:00
2025-01-17 15:23:17 +00:00
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;
}
2025-01-02 22:48:28 +00:00
var @lock = new RedisDistributedLock(resource, redis.GetDatabase());
2024-07-15 21:38:47 +00:00
await using (var handle = await @lock.TryAcquireAsync(timeout))
2024-04-30 12:50:01 +00:00
{
2024-08-21 15:26:36 +00:00
if (handle == null)
2024-04-30 12:50:01 +00:00
{
2024-11-08 20:53:04 +00:00
_logger.LogWarning($"Acquire lock for {resource} failed due to after {timeout}s timeout.");
2024-12-03 22:52:14 +00:00
return false;
2024-07-15 21:38:47 +00:00
}
2024-08-21 15:26:36 +00:00
2024-12-03 22:52:14 +00:00
await action();
return true;
2024-04-30 12:50:01 +00:00
}
}
2024-11-08 20:53:04 +00:00
public bool Lock(string resource, Action action, int timeoutInSeconds = 30)
2024-04-30 12:50:01 +00:00
{
2024-08-21 19:48:12 +00:00
var timeout = TimeSpan.FromSeconds(timeoutInSeconds);
2024-08-21 18:41:52 +00:00
2025-01-02 22:48:28 +00:00
var redis = _services.GetRequiredService<IConnectionMultiplexer>();
var @lock = new RedisDistributedLock(resource, redis.GetDatabase());
2024-11-05 13:29:06 +00:00
using (var handle = @lock.TryAcquire(timeout))
2024-04-30 12:50:01 +00:00
{
2024-08-21 16:23:24 +00:00
if (handle == null)
2024-04-30 12:50:01 +00:00
{
2024-11-08 20:53:04 +00:00
_logger.LogWarning($"Acquire lock for {resource} failed due to after {timeout}s timeout.");
return false;
2024-04-30 12:50:01 +00:00
}
2024-11-05 13:29:06 +00:00
else
{
action();
2024-11-08 20:53:04 +00:00
return true;
2024-11-05 13:29:06 +00:00
}
}
}
2024-04-30 12:50:01 +00:00
}