bilal-kilic
3/15/2019 - 1:00 PM

ItemHashPairCacheService

 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}";
        }