Beispiel #1
0
        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())));
        }
Beispiel #2
0
        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()));
        }