using System.Collections.Concurrent;
using adas_core.Application.Services.Interfaces;
namespace adas_core.Application.Services.Caching
{
///
/// Implementación local del sistema de locking por clave.
/// Se basa en SemaphoreSlim y solo controla concurrencia DENTRO del proceso.
/// Para CacheService (in-memory).
///
///
public class InMemoryLockProvider : ILockProvider
{
private readonly ConcurrentDictionary _locks = new(StringComparer.Ordinal);
///
/// Crea u obtiene un semáforo asociado a la clave.
///
///
private SemaphoreSlim GetOrCreate(string key)
{
return _locks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));
}
///
/// Intenta adquirir el lock por clave.
///
///
///
///
public async Task 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);
}
}
///
/// Libera el lock (si existe y no está ya liberado).
///
///
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;
}
}
}