Files
adas-core/adas-core.Application/Services/Caching/CacheDispatcher.cs
T

111 lines
4.3 KiB
C#

using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Utils;
using MongoDB.Bson;
namespace adas_core.Application.Services.Caching
{
/// <summary>
/// Orquestador de caché. Selecciona el backend (Redis, InMemory, None)
/// según CacheSettings y la entidad del key.
/// Implementa ICacheService y delega en el backend elegido.
/// </summary>
public class CacheDispatcher(
RedisService redis,
CacheService memory,
NoCacheService noop,
CacheSettings cacheSettings)
: ICacheService
{
// Selección de backend
private ICacheService SelectBackend(string key)
{
var entity = CacheKeyClassifier.Classify(key);
var mode = entity switch
{
CacheEnum.EntityType.Patients => cacheSettings.Patients,
CacheEnum.EntityType.Displays => cacheSettings.Displays,
CacheEnum.EntityType.PumpObservations => cacheSettings.PumpObservations,
CacheEnum.EntityType.Appointments => cacheSettings.Appointments,
CacheEnum.EntityType.GroupedObservations => cacheSettings.GroupedObservations,
_ => CacheEnum.Mode.Cache
};
return mode switch
{
CacheEnum.Mode.Redis => redis,
CacheEnum.Mode.Cache => memory,
_ => noop
};
}
// Para GroupedObservations generamos la misma clave compuesta que el resto de servicios,
// de modo que el clasificador y la política de TTL funcionen igual.
private static string BuildGroupedKey(GroupedField gf, ObjectId patientId)
=> $"GroupedObs:{patientId}:{gf.Name}";
private ICacheService SelectBackend(GroupedField groupedField, ObjectId patientId)
=> SelectBackend(BuildGroupedKey(groupedField, patientId));
// GetOrSet (KEY string)
public Task<T> GetOrSetObjectAsync<T>(
string key,
Func<Task<T>> factory,
TimeSpan? ttl = null,
CancellationToken cancellationToken = default)
=> SelectBackend(key).GetOrSetObjectAsync(key, factory, ttl, cancellationToken);
public Task<string?> GetOrSetValueAsync(
string key,
Func<Task<string>> loader,
TimeSpan? ttl = null)
=> SelectBackend(key).GetOrSetValueAsync(key, loader, ttl);
// GetOrSet (GroupedField + PatientId)
public Task<T> GetOrSetObjectAsync<T>(
GroupedField groupedField,
ObjectId patientId,
Func<Task<T>> factory,
TimeSpan? ttl = null,
CancellationToken cancellationToken = default)
=> SelectBackend(groupedField, patientId)
.GetOrSetObjectAsync(groupedField, patientId, factory, ttl, cancellationToken);
// Set/Get básicos
public void SetValue(string key, string value)
=> SelectBackend(key).SetValue(key, value);
public string? GetValue(string key)
=> SelectBackend(key).GetValue(key);
public Task<T?> GetObjectAsync<T>(string key, bool upd = true)
=> SelectBackend(key).GetObjectAsync<T>(key, upd);
public Task SetObjectAsync<T>(string key, T obj, bool upd = true)
=> SelectBackend(key).SetObjectAsync(key, obj, upd);
public Task<T?> GetObjectAsync<T>(string key, TimeSpan? ttl, bool upd)
=> SelectBackend(key).GetObjectAsync<T>(key, ttl, upd);
public Task SetObjectAsync<T>(string key, T obj, TimeSpan? ttl, bool upd)
=> SelectBackend(key).SetObjectAsync(key, obj, ttl, upd);
public Task DeleteObjectAsync(string key)
=> SelectBackend(key).DeleteObjectAsync(key);
public async Task<long> DeleteByPatternAsync(string pattern)
=> await redis.DeleteByPatternAsync(pattern) + await memory.DeleteByPatternAsync(pattern);
public void CleanCache()
{
memory.CleanCache();
redis.CleanCache();
}
}
}