using Managing.Application.Abstractions; using Managing.Core; //using Microsoft.Extensions.Caching.Memory; using System.Runtime.Caching; namespace Managing.Infrastructure.Storage { public class TaskCache : ITaskCache { private MemoryCache _cache { get; } = MemoryCache.Default; private CacheItemPolicy _defaultPolicy { get; } = new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromMinutes(15), }; public async Task AddOrGetExisting(string key, Func> valueFactory) { var asyncLazyValue = new AsyncLazy(valueFactory); var existingValue = (AsyncLazy)_cache.AddOrGetExisting(key, asyncLazyValue, _defaultPolicy); if (existingValue != null) { asyncLazyValue = existingValue; } try { var result = await asyncLazyValue; // The awaited Task has completed. Check that the task still is the same version // that the cache returns (i.e. the awaited task has not been invalidated during the await). if (asyncLazyValue != _cache.AddOrGetExisting(key, new AsyncLazy(valueFactory), _defaultPolicy)) { // The awaited value is no more the most recent one. // Get the most recent value with a recursive call. return await AddOrGetExisting(key, valueFactory); } return result; } catch (Exception) { // Task object for the given key failed with exception. Remove the task from the cache. _cache.Remove(key); // Re throw the exception to be handled by the caller. throw; } } public void Invalidate(string key) { _cache.Remove(key); } public bool Contains(string key) { return _cache.Contains(key); } public void Clear() { // A snapshot of keys is taken to avoid enumerating collection during changes. var keys = _cache.Select(i => i.Key).ToList(); keys.ForEach(k => _cache.Remove(k)); } public T Get(string key) { var existingValue = (AsyncLazy)_cache.Get(key); if (existingValue != null) return existingValue.Value.Result; return default(T); } public virtual List GetCache() { List list = new List(); foreach (var item in _cache) { list.Add((T)item.Value); } return list; } } }