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; } } }