Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop

This commit is contained in:
jrojas
2026-06-26 09:52:35 +02:00
commit 319fd3dfb0
746 changed files with 106610 additions and 0 deletions
@@ -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;
}
}
}