Beispiel #1
0
        private async Task ProcessWithMemoryCache(HttpContext context, string cacheKey, ImageJobInfo info)
        {
            var isCached            = memoryCache.TryGetValue(cacheKey, out ArraySegment <byte> imageBytes);
            var isContentTypeCached = memoryCache.TryGetValue(cacheKey + ".contentType", out string contentType);

            if (isCached && isContentTypeCached)
            {
                logger?.LogInformation("Serving {0}?{1} from memory cache", info.FinalVirtualPath, info.CommandString);
            }
            else
            {
                if (info.HasParams)
                {
                    logger?.LogInformation($"Memory Cache Miss: Processing image {info.FinalVirtualPath}?{info.CommandString}");

                    var imageData = await info.ProcessUncached();

                    imageBytes  = imageData.ResultBytes;
                    contentType = imageData.ContentType;
                }
                else
                {
                    logger?.LogInformation($"Memory Cache Miss: Proxying image {info.FinalVirtualPath}?{info.CommandString}");

                    contentType = PathHelpers.ContentTypeForImageExtension(info.EstimatedFileExtension);
                    imageBytes  = new ArraySegment <byte>(await info.GetPrimaryBlobBytesAsync());
                }

                // Set cache options.
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                                        .SetSize(imageBytes.Count)
                                        .SetSlidingExpiration(options.MemoryCacheSlidingExpiration);

                var cacheEntryMetaOptions = new MemoryCacheEntryOptions()
                                            .SetSize(contentType.Length * 2)
                                            .SetSlidingExpiration(options.MemoryCacheSlidingExpiration);

                memoryCache.Set(cacheKey, imageBytes, cacheEntryOptions);
                memoryCache.Set(cacheKey + ".contentType", contentType, cacheEntryMetaOptions);
            }

            // write to stream
            context.Response.ContentType   = contentType;
            context.Response.ContentLength = imageBytes.Count;
            SetCachingHeaders(context, cacheKey);


            await context.Response.Body.WriteAsync(imageBytes.Array, imageBytes.Offset, imageBytes.Count);
        }
Beispiel #2
0
        private async Task ProcessWithDistributedCache(HttpContext context, string cacheKey, ImageJobInfo info)
        {
            var imageBytes = await distributedCache.GetAsync(cacheKey);

            var contentType = await distributedCache.GetStringAsync(cacheKey + ".contentType");

            if (imageBytes != null && contentType != null)
            {
                logger?.LogInformation("Serving {0}?{1} from distributed cache", info.FinalVirtualPath, info.CommandString);
            }
            else
            {
                if (info.HasParams)
                {
                    logger?.LogInformation($"Distributed Cache Miss: Processing image {info.FinalVirtualPath}?{info.CommandString}");

                    var imageData = await info.ProcessUncached();

                    imageBytes = imageData.ResultBytes.Count != imageData.ResultBytes.Array?.Length
                        ? imageData.ResultBytes.ToArray()
                        : imageData.ResultBytes.Array;

                    contentType = imageData.ContentType;
                }
                else
                {
                    logger?.LogInformation($"Distributed Cache Miss: Proxying image {info.FinalVirtualPath}?{info.CommandString}");

                    contentType = PathHelpers.ContentTypeForImageExtension(info.EstimatedFileExtension);
                    imageBytes  = await info.GetPrimaryBlobBytesAsync();
                }

                // Set cache options.
                var cacheEntryOptions = new DistributedCacheEntryOptions()
                                        .SetSlidingExpiration(options.DistributedCacheSlidingExpiration);

                await distributedCache.SetAsync(cacheKey, imageBytes, cacheEntryOptions);

                await distributedCache.SetStringAsync(cacheKey + ".contentType", contentType, cacheEntryOptions);
            }

            // write to stream
            context.Response.ContentType   = contentType;
            context.Response.ContentLength = imageBytes.Length;
            SetCachingHeaders(context, cacheKey);

            await context.Response.Body.WriteAsync(imageBytes, 0, imageBytes.Length);
        }
Beispiel #3
0
        private async Task ProcessWithStreamCache(HttpContext context, string cacheKey, ImageJobInfo info)
        {
            var keyBytes    = Encoding.UTF8.GetBytes(cacheKey);
            var typeName    = streamCache.GetType().Name;
            var cacheResult = await streamCache.GetOrCreateBytes(keyBytes, async (cancellationToken) =>
            {
                if (info.HasParams)
                {
                    logger?.LogDebug("{CacheName} miss: Processing image {VirtualPath}?{Querystring}", typeName, info.FinalVirtualPath, info.ToString());
                    var result = await info.ProcessUncached();
                    if (result.ResultBytes.Array == null)
                    {
                        throw new InvalidOperationException("Image job returned zero bytes.");
                    }
                    return(new Tuple <string, ArraySegment <byte> >(result.ContentType, result.ResultBytes));
                }

                logger?.LogDebug("{CacheName} miss: Proxying image {VirtualPath}", typeName, info.FinalVirtualPath);
                var bytes = await info.GetPrimaryBlobBytesAsync();
                return(new Tuple <string, ArraySegment <byte> >(null, bytes));
            }, CancellationToken.None, false);

            if (cacheResult.Status != null)
            {
                GlobalPerf.Singleton.IncrementCounter($"{typeName}_{cacheResult.Status}");
            }
            if (cacheResult.Data != null)
            {
                await using (cacheResult.Data)
                {
                    if (cacheResult.Data.Length < 1)
                    {
                        throw new InvalidOperationException($"{typeName} returned cache entry with zero bytes");
                    }
                    SetCachingHeaders(context, cacheKey);
                    await MagicBytes.ProxyToStream(cacheResult.Data, context.Response);
                }
                logger?.LogDebug("Serving from {CacheName} {VirtualPath}?{CommandString}", typeName, info.FinalVirtualPath, info.CommandString);
            }
            else
            {
                // TODO explore this failure path better
                throw new NullReferenceException("Caching failed: " + cacheResult.Status);
            }
        }
Beispiel #4
0
        private async Task ProcessWithSqliteCache(HttpContext context, string cacheKey, ImageJobInfo info)
        {
            var cacheResult = await sqliteCache.GetOrCreate(cacheKey, async() =>
            {
                if (info.HasParams)
                {
                    logger?.LogInformation($"Sqlite Cache Miss: Processing image {info.FinalVirtualPath}?{info.CommandString}");

                    var imageData  = await info.ProcessUncached();
                    var imageBytes = imageData.ResultBytes.Count != imageData.ResultBytes.Array?.Length
                        ? imageData.ResultBytes.ToArray()
                        : imageData.ResultBytes.Array;

                    var contentType = imageData.ContentType;
                    return(new SqliteCacheEntry()
                    {
                        ContentType = contentType,
                        Data = imageBytes
                    });
                }
                else
                {
                    logger?.LogInformation($"Sqlite Cache Miss: Proxying image {info.FinalVirtualPath}?{info.CommandString}");

                    var contentType = PathHelpers.ContentTypeForImageExtension(info.EstimatedFileExtension);
                    return(new SqliteCacheEntry()
                    {
                        ContentType = contentType,
                        Data = await info.GetPrimaryBlobBytesAsync()
                    });
                }
            });


            // write to stream
            context.Response.ContentType   = cacheResult.ContentType;
            context.Response.ContentLength = cacheResult.Data.Length;
            SetCachingHeaders(context, cacheKey);

            await context.Response.Body.WriteAsync(cacheResult.Data, 0, cacheResult.Data.Length);
        }