public void Displayed(ShapeDisplayedContext context) { // TODO: Configure duration of sliding expiration var cacheContext = context.ShapeMetadata.Cache(); // If the shape is not cached, evaluate the ESIs if (cacheContext == null) { string content; using (var sw = new StringWriter()) { context.ChildContent.WriteTo(sw, HtmlEncoder.Default); content = sw.ToString(); } ProcessESIs(ref content, GetDistributedCache); context.ChildContent = new HtmlString(content); } else if (!_cached.Contains(cacheContext) && context.ChildContent != null) { var cacheEntries = GetCacheEntries(cacheContext).ToList(); string cacheKey = GetCacheKey(cacheContext.CacheId, cacheEntries); using (var sw = new StringWriter()) { context.ChildContent.WriteTo(sw, HtmlEncoder.Default); var content = sw.ToString(); _cached.Add(cacheContext); _cache[cacheKey] = content; var contexts = String.Join(ContextSeparator.ToString(), cacheContext.Contexts.ToArray()); context.ChildContent = new HtmlString($"[[cache id='{cacheContext.CacheId}' contexts='{contexts}']]"); var bytes = Encoding.UTF8.GetBytes(content); // Default duration is sliding expiration (permanent as long as it's used) DistributedCacheEntryOptions options = new DistributedCacheEntryOptions { SlidingExpiration = new TimeSpan(0, 1, 0) }; // If a custom duration is specified, replace the default options if (cacheContext.Duration.HasValue) { options = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = cacheContext.Duration }; } _dynamicCache.SetAsync(cacheKey, bytes, options).Wait(); _tagCache.Tag(cacheKey, cacheContext.Tags.ToArray()); } } }
private async Task SetCachedValueAsync(string cacheKey, string value, CacheContext context) { var failover = _memoryCache.Get <bool>(FailoverKey); if (failover) { return; } var bytes = Encoding.UTF8.GetBytes(value); var options = new DistributedCacheEntryOptions { AbsoluteExpiration = context.ExpiresOn, SlidingExpiration = context.ExpiresSliding, AbsoluteExpirationRelativeToNow = context.ExpiresAfter }; // Default duration is sliding expiration (permanent as long as it's used) if (!options.AbsoluteExpiration.HasValue && !options.SlidingExpiration.HasValue && !options.AbsoluteExpirationRelativeToNow.HasValue) { options.SlidingExpiration = new TimeSpan(0, 1, 0); } try { await _dynamicCache.SetAsync(cacheKey, bytes, options); } catch (Exception e) { _logger.LogError(e, "Failed to write the '{CacheKey}' to the dynamic cache", cacheKey); _memoryCache.Set(FailoverKey, true, new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = _dynamicCacheOptions.FailoverRetryLatency }); return; } // Lazy load to prevent cyclic dependency _tagcache ??= _serviceProvider.GetRequiredService <ITagCache>(); await _tagcache.TagAsync(cacheKey, context.Tags.ToArray()); }
private async Task SetCachedValueAsync(string cacheKey, string value, CacheContext context) { var bytes = Encoding.UTF8.GetBytes(value); var options = new DistributedCacheEntryOptions { AbsoluteExpiration = context.ExpiresOn, SlidingExpiration = context.ExpiresSliding, AbsoluteExpirationRelativeToNow = context.ExpiresAfter }; // Default duration is sliding expiration (permanent as long as it's used) if (!options.AbsoluteExpiration.HasValue && !options.SlidingExpiration.HasValue && !options.AbsoluteExpirationRelativeToNow.HasValue) { options.SlidingExpiration = new TimeSpan(0, 1, 0); } await _dynamicCache.SetAsync(cacheKey, bytes, options); // Lazy load to prevent cyclic dependency _tagcache ??= _serviceProvider.GetRequiredService <ITagCache>(); await _tagcache.TagAsync(cacheKey, context.Tags.ToArray()); }