Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using System.Collections.Concurrent;
|
||||
using adas_core.Application.Services.Interfaces;
|
||||
|
||||
namespace adas_core.Application.Services.Caching
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementación local del sistema de locking por clave.
|
||||
/// Se basa en SemaphoreSlim y solo controla concurrencia DENTRO del proceso.
|
||||
/// Para CacheService (in-memory).
|
||||
/// </summary>
|
||||
public class InMemoryLockProvider : ILockProvider
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new(StringComparer.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// Crea u obtiene un semáforo asociado a la clave.
|
||||
/// </summary>
|
||||
private SemaphoreSlim GetOrCreate(string key)
|
||||
{
|
||||
return _locks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intenta adquirir el lock por clave.
|
||||
/// </summary>
|
||||
public async Task<bool> AcquireAsync(string key, TimeSpan timeout)
|
||||
{
|
||||
var sem = GetOrCreate(key);
|
||||
|
||||
try
|
||||
{
|
||||
return await sem.WaitAsync(timeout).ConfigureAwait(false);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// Si el semáforo se eliminó entre medio, creamos uno nuevo.
|
||||
_locks.TryRemove(key, out _);
|
||||
return await GetOrCreate(key).WaitAsync(timeout).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Libera el lock (si existe y no está ya liberado).
|
||||
/// </summary>
|
||||
public Task ReleaseAsync(string key)
|
||||
{
|
||||
if (!_locks.TryGetValue(key, out var sem))
|
||||
return Task.CompletedTask;
|
||||
|
||||
try
|
||||
{
|
||||
sem.Release();
|
||||
}
|
||||
catch (SemaphoreFullException)
|
||||
{
|
||||
// Idempotencia: ignoramos exceso de releases
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user