=== Summary: 675 files | 7 generated | 484 fresh | 4605 untracked | 4268 adopted | 355 marked | 466 validated-ok | 2+0 stale (sig+body) | 0 skipped | 0 failed | elapsed 11:08:11.442 (40091.44s) ===
This commit is contained in:
@@ -16,6 +16,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <summary>
|
||||
/// Represents a Redis-based implementation of the <see cref="ICacheService"/> interface for caching operations.
|
||||
/// </summary>
|
||||
/// <!-- aidoc:v1 sig=a3787ed -->
|
||||
public class RedisService : ICacheService
|
||||
{
|
||||
private readonly ILogger<RedisService> _logger;
|
||||
@@ -59,6 +60,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="ttl">Optional time-to-live duration for the cached object. If null, the cache default is used.</param>
|
||||
/// <param name="cancellationToken">The token used to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation, containing the cached or newly created object.</returns>
|
||||
/// <!-- aidoc:v1 sig=df20281 body=dc4ffdf -->
|
||||
public async Task<T> GetOrSetObjectAsync<T>(
|
||||
string key,
|
||||
Func<Task<T>> factory,
|
||||
@@ -100,6 +102,8 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="loader">The asynchronous function invoked to produce the value when it is not present in the cache.</param>
|
||||
/// <param name="ttl">Optional time-to-live applied to the cached value; if not provided, the default caching policy is used.</param>
|
||||
/// <returns>The cached value when available, or the value produced by the loader when the cache is empty or Redis is unavailable.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=mentions_removed_behavior
|
||||
/// "The ttl parameter is documented as 'applied to the cached value', but the code never references or passes ttl to SetValue; the parameter is unused in the method body." -->
|
||||
public async Task<string?> GetOrSetValueAsync(
|
||||
string key,
|
||||
Func<Task<string>> loader,
|
||||
@@ -136,6 +140,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="gf">The grouped field whose name is used to identify the observation group.</param>
|
||||
/// <param name="patientId">The identifier of the patient the observation belongs to.</param>
|
||||
/// <returns>A formatted string key combining the <c>GroupedObs</c> prefix, the patient identifier, and the grouped field name.</returns>
|
||||
/// <!-- aidoc:v1 sig=72c65a6 -->
|
||||
private static string BuildGroupedKey(GroupedField gf, ObjectId patientId)
|
||||
=> $"GroupedObs:{patientId}:{gf.Name}";
|
||||
|
||||
@@ -148,6 +153,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="ttl">Optional time-to-live applied to the stored cache entry. If null, no expiration is set.</param>
|
||||
/// <param name="cancellationToken">Token used to cancel the distributed lock operation.</param>
|
||||
/// <returns>The cached object if present, otherwise the object produced by <paramref name="factory"/>.</returns>
|
||||
/// <!-- aidoc:v1 sig=f122a12 body=a3fec17 -->
|
||||
public async Task<T> GetOrSetObjectAsync<T>(
|
||||
GroupedField groupedField,
|
||||
ObjectId patientId,
|
||||
@@ -190,6 +196,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// </summary>
|
||||
/// <param name="key">The key under which the value will be stored.</param>
|
||||
/// <param name="value">The string value to persist.</param>
|
||||
/// <!-- aidoc:v1 sig=fb46470 -->
|
||||
public void SetValue(string key, string value)
|
||||
=> _database?.StringSet(key, value, GetEntityTtl(key), true);
|
||||
|
||||
@@ -198,6 +205,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// </summary>
|
||||
/// <param name="key">The identifier of the value to look up in the data store.</param>
|
||||
/// <returns>The stored string value, or <c>null</c> if the key does not exist or the data store is unavailable.</returns>
|
||||
/// <!-- aidoc:v1 sig=39e4be0 body=3910e79 -->
|
||||
public string? GetValue(string key)
|
||||
{
|
||||
var val = _database?.StringGet(key);
|
||||
@@ -214,6 +222,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="updateExpiration">When <c>true</c> (the default), resets the key's time-to-live to the configured entity TTL on a successful read, implementing sliding expiration.</param>
|
||||
/// <returns>A <see cref="Task{T}"/> containing the deserialized object, or <c>default</c> if Redis is unavailable or the key is missing/empty.</returns>
|
||||
/// <exception cref="Exception">Thrown when the stored JSON payload cannot be deserialized into <typeparamref name="T"/>; the original exception is wrapped and rethrown.</exception>
|
||||
/// <!-- aidoc:v1 sig=a7a96b7 body=6c885c8 -->
|
||||
public async Task<T?> GetObjectAsync<T>(string key, bool updateExpiration = true)
|
||||
{
|
||||
if (!_isRedisAvailable)
|
||||
@@ -248,6 +257,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="key">The key under which the object will be stored.</param>
|
||||
/// <param name="obj">The object to store.</param>
|
||||
/// <param name="updateExpiration">Indicates whether the expiration time of the entry should be updated.</param>
|
||||
/// <!-- aidoc:v1 sig=2dac8a4 -->
|
||||
public async Task SetObjectAsync<T>(
|
||||
string key,
|
||||
T obj,
|
||||
@@ -261,6 +271,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="obj">The object to serialize and persist to Redis.</param>
|
||||
/// <param name="ttlOverride">An optional time-to-live override; when null, the entity's default TTL is applied.</param>
|
||||
/// <param name="updateExpiration">Flag indicating whether the expiration should be updated.</param>
|
||||
/// <!-- aidoc:v1 sig=b181b67 body=11fd650 -->
|
||||
public async Task SetObjectAsync<T>(
|
||||
string key,
|
||||
T obj,
|
||||
@@ -283,6 +294,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// When the Redis backend is unavailable, the call is skipped silently as a no-op fallback.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique identifier of the cached object to remove.</param>
|
||||
/// <!-- aidoc:v1 sig=884f4b6 body=00b8917 -->
|
||||
public async Task DeleteObjectAsync(string key)
|
||||
{
|
||||
if (_isRedisAvailable)
|
||||
@@ -295,6 +307,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern used to match Redis keys to be deleted.</param>
|
||||
/// <returns>The number of keys that were deleted.</returns>
|
||||
/// <!-- aidoc:v1 sig=691e7ee body=f96f2c9 -->
|
||||
public async Task<long> DeleteByPatternAsync(string pattern)
|
||||
{
|
||||
if (!_isRedisAvailable || _server == null)
|
||||
@@ -311,6 +324,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <summary>
|
||||
/// Clears all cached data by flushing the underlying server database. If the server instance is <see langword="null"/>, the call is safely skipped as a no-op.
|
||||
/// </summary>
|
||||
/// <!-- aidoc:v1 sig=f510ade -->
|
||||
public void CleanCache()
|
||||
=> _server?.FlushDatabase();
|
||||
|
||||
@@ -321,6 +335,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// </summary>
|
||||
/// <param name="key">The cache key used to classify the entity type and determine the applicable TTL.</param>
|
||||
/// <returns>A <see cref="TimeSpan"/> representing the configured TTL, or <c>null</c> if the resolved seconds value is not positive.</returns>
|
||||
/// <!-- aidoc:v1 sig=be2ec4a body=d7d015b -->
|
||||
private TimeSpan? GetEntityTtl(string key)
|
||||
{
|
||||
var entity = CacheKeyClassifier.Classify(key);
|
||||
@@ -341,6 +356,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// </summary>
|
||||
/// <param name="key">The key identifying the entity whose TTL presence is being checked.</param>
|
||||
/// <returns><c>true</c> if a TTL value is found for the specified key; otherwise, <c>false</c>.</returns>
|
||||
/// <!-- aidoc:v1 sig=9f4c827 -->
|
||||
private bool ShouldRenewTtl(string key)
|
||||
=> GetEntityTtl(key) != null;
|
||||
|
||||
@@ -349,6 +365,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <summary>
|
||||
/// Initializes the Redis connection for caching by connecting asynchronously, obtaining the database and server, and marking the connection as available on success. Returns early without establishing a connection when the configured Redis connection string is null, and logs any exception that occurs during initialization without rethrowing, leaving the connection marked as unavailable.
|
||||
/// </summary>
|
||||
/// <!-- aidoc:v1 sig=819c56e body=e2d6e2b -->
|
||||
private async Task InitializeRedisConnectionAsync()
|
||||
{
|
||||
_isRedisAvailable = false;
|
||||
@@ -377,6 +394,7 @@ namespace adas_core.Application.Services.Caching
|
||||
/// <param name="ttlOverride">An optional time-to-live override; not applied by this overload.</param>
|
||||
/// <param name="updateExpiration">When true, the expiration of the cached entry is refreshed on retrieval.</param>
|
||||
/// <returns>A task that resolves to the cached object, or null if no entry exists for the specified key.</returns>
|
||||
/// <!-- aidoc:v1 sig=dc7158d -->
|
||||
public Task<T?> GetObjectAsync<T>(string key, TimeSpan? ttlOverride, bool updateExpiration)
|
||||
=> GetObjectAsync<T>(key, updateExpiration);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user