Task <StorageItemDownloadInfo?> IStorageCache.GetItemAsync(string path, CancellationToken?cancellationToken = null) { if (_cache == null) { throw new Exception("Cache is not initialized"); } var cacheEntry = CacheExtensions.Get <TRecord?>(_cache, NormalizePath(path)); return(Task.FromResult <StorageItemDownloadInfo?>(cacheEntry is null ? null : new StorageItemDownloadInfo(cacheEntry.FileSize, cacheEntry.Date, () => cacheEntry.OpenRead()))); }
async Task <StorageItemDownloadInfo?> IStorageCache.GetOrAddItemAsync(string path, Func <Task <StorageItemDownloadInfo?> > addItem, CancellationToken?cancellationToken = null) { if (_cache == null) { throw new Exception("Cache is not initialized"); } var key = NormalizePath(path); if (!CacheExtensions.TryGetValue(_cache, key, out TRecord? cacheEntry)) // Look for cache key. { var itemLock = _locks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); await itemLock.WaitAsync(cancellationToken ?? CancellationToken.None); try { if (!CacheExtensions.TryGetValue(_cache, key, out cacheEntry)) { var result = await addItem(); if (result == null) { Logger.LogDebug("File {File} not found", key); return(null); } if (Options.MaxFileSizeToStore > 0 && result.FileSize > Options.MaxFileSizeToStore) { Logger.LogWarning( "File {Key} exceed maximum cache file size. File size: {FleSize}. Maximum size: {MaximumSize}", key, result.FileSize, Helpers.HumanSize(Options.MaxFileSizeToStore)); return(result); } var stream = result.GetStream(); await using (stream) { Logger.LogDebug("Download file {Key}", key); cacheEntry = await GetEntryAsync(result, stream, cancellationToken); var options = new MemoryCacheEntryOptions { SlidingExpiration = Options.Ttl }; options.RegisterPostEvictionCallback((_, value, _, _) => { if (value is TRecord deletedRecord) { DisposeItem(deletedRecord); } Logger.LogDebug("Remove file {ObjKey} from cache", key); }); if (Options.MaxCacheSize > 0) { options.Size = result.FileSize; } Logger.LogDebug("Add file {Key} to cache", key); _cache.Set(key, cacheEntry, options); } } } catch (Exception ex) { Logger.LogError(ex, "Error caching file {File}: {ErrorText}", key, ex.ToString()); return(null); } finally { itemLock.Release(); } } return(cacheEntry is null ? null : new StorageItemDownloadInfo(/*cacheEntry.Metadata, */ cacheEntry.FileSize, cacheEntry.Date, () => cacheEntry.OpenRead())); }