public sealed class ItemHashPairCacheService : IItemHashPairCacheService
{
private readonly ICacheClient _cacheClient;
private readonly ILogger<ItemHashPairCacheService> _logger;
private static readonly TimeSpan CacheExpiry = TimeSpan.FromDays(30);
public ItemHashPairCacheService(ICacheClient cacheClient, ILogger<ItemHashPairCacheService> logger)
{
_cacheClient = cacheClient ?? throw new ArgumentNullException(nameof(cacheClient));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<Dictionary<string, InvalidationValue>> Get<T>(ItemHashPair<T>[] itemHashPairs)
{
try
{
RedisKey[] redisKeys = itemHashPairs
.Select(x => CreateKey(x.Key))
.Distinct()
.ToArray();
return (await _cacheClient.Database.StringGetAsync(redisKeys))
.Where(r => r.HasValue && string.IsNullOrEmpty(r) == false)
.Select(v =>
{
try
{
return JsonConvert.DeserializeObject<InvalidationValue>(v);
}
catch (Exception)
{
return null;
}
})
.Where(r => r != null)
.ToDictionary(x => x.Key);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occured when reading data from redis", ex);
return new Dictionary<string, InvalidationValue>();
}
}
public async Task<ItemHashPair<T>[]> GetChangedPairs<T>(ItemHashPair<T>[] itemHashPairs)
{
Dictionary<string, InvalidationValue> existingItems = await Get(itemHashPairs);
return itemHashPairs.Where(ip => !existingItems.TryGetValue(ip.Key, out InvalidationValue iv) || !string.Equals(iv.Hash, ip.Hash))
.Distinct()
.ToArray();
}
public async Task Put<T>(ItemHashPair<T>[] itemHashPairs)
{
try
{
var redisPayloads = itemHashPairs
.Select(p =>
{
string v = JsonConvert.SerializeObject(new InvalidationValue()
{
Key = p.Key,
Hash = p.Hash
});
return new
{
key = CreateKey(p.Key),
payload = v
};
})
.ToList();
var list = new List<Task<bool>>();
foreach (var v in redisPayloads)
{
Task<bool> t = _cacheClient.Database.StringSetAsync(v.key, v.payload, CacheExpiry);
list.Add(t);
}
await Task.WhenAll(list);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occured when", ex);
}
}
private static RedisKey CreateKey(string key)
{
return $"cacheclient::barcode::{key}";
}