Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
using adas_core.Application.Services.Interfaces;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using MongoDB.Bson;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace adas_core.Application.Services.Caching
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementación de caché en memoria con soporte de locking seguro
|
||||
/// mediante LockManagerService + InMemoryLockProvider.
|
||||
/// Compatible con la interfaz ICacheService incluyendo GetOrSet.
|
||||
/// </summary>
|
||||
public class CacheService(LockManagerService lockManager) : ICacheService
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, object> _mem = new();
|
||||
|
||||
// HELPERS
|
||||
private static string BuildGroupedKey(GroupedField gf, ObjectId patientId)
|
||||
=> $"GroupedObs:{patientId}:{gf.Name}";
|
||||
|
||||
|
||||
// GET OR SET (string key)
|
||||
public async Task<T> GetOrSetObjectAsync<T>(
|
||||
string key,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// FAST PATH
|
||||
if (_mem.TryGetValue(key, out var existing))
|
||||
return (T)existing;
|
||||
|
||||
// LOCKED PATH
|
||||
return await lockManager.WithLockAsync(
|
||||
$"getorset:{key}",
|
||||
TimeSpan.FromSeconds(5),
|
||||
async () =>
|
||||
{
|
||||
if (_mem.TryGetValue(key, out var again))
|
||||
return (T)again;
|
||||
|
||||
var created = await factory();
|
||||
|
||||
if (created != null!)
|
||||
_mem[key] = created;
|
||||
|
||||
return created!;
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<string?> GetOrSetValueAsync(
|
||||
string key,
|
||||
Func<Task<string>> loader,
|
||||
TimeSpan? ttlOverride = null)
|
||||
{
|
||||
|
||||
var result = await GetOrSetObjectAsync(key, loader, ttlOverride);
|
||||
return (string?)result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// GET OR SET (GroupedField + patientId)
|
||||
public async Task<T> GetOrSetObjectAsync<T>(
|
||||
GroupedField groupedField,
|
||||
ObjectId patientId,
|
||||
Func<Task<T>> factory,
|
||||
TimeSpan? ttl = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var key = BuildGroupedKey(groupedField, patientId);
|
||||
|
||||
if (_mem.TryGetValue(key, out var existing))
|
||||
return (T)existing;
|
||||
|
||||
return await lockManager.WithLockAsync(
|
||||
$"getorset:{key}",
|
||||
TimeSpan.FromSeconds(5),
|
||||
async () =>
|
||||
{
|
||||
if (_mem.TryGetValue(key, out var again))
|
||||
return (T)again;
|
||||
|
||||
var created = await factory();
|
||||
|
||||
if (created != null!)
|
||||
_mem[key] = created;
|
||||
|
||||
return created!;
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
// GET / SET
|
||||
public void SetValue(string key, string value)
|
||||
=> _mem[key] = value;
|
||||
|
||||
public string? GetValue(string key)
|
||||
=> _mem.TryGetValue(key, out var v) ? v.ToString() : null;
|
||||
|
||||
public Task<T?> GetObjectAsync<T>(string key, bool updateExpiration = true)
|
||||
{
|
||||
return Task.FromResult(
|
||||
_mem.TryGetValue(key, out var v) ? (T?)v : default
|
||||
);
|
||||
}
|
||||
|
||||
public Task SetObjectAsync<T>(string key, T obj, bool updateExpiration = true)
|
||||
{
|
||||
_mem[key] = obj!;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<T?> GetObjectAsync<T>(string key, TimeSpan? ttlOverride, bool upd)
|
||||
=> GetObjectAsync<T>(key, upd);
|
||||
|
||||
public Task SetObjectAsync<T>(string key, T obj, TimeSpan? ttlOverride, bool upd)
|
||||
=> SetObjectAsync(key, obj, upd);
|
||||
|
||||
|
||||
// DELETE / CLEAN
|
||||
public Task DeleteObjectAsync(string key)
|
||||
{
|
||||
_mem.TryRemove(key, out _);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<long> DeleteByPatternAsync(string pattern)
|
||||
{
|
||||
var p = pattern.Replace("*", "");
|
||||
var keys = _mem.Keys.Where(k => k.Contains(p)).ToList();
|
||||
|
||||
long removed = 0;
|
||||
foreach (var k in keys)
|
||||
if (_mem.TryRemove(k, out _))
|
||||
removed++;
|
||||
|
||||
return Task.FromResult(removed);
|
||||
}
|
||||
|
||||
public void CleanCache() => _mem.Clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user