/// <summary> /// Sets the item with the given key. /// </summary> /// <typeparam name="T">The item type.</typeparam> /// <param name="cache">The <see cref="IDistributedCache"/>.</param> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="methodCacheOptions">Optional method cache options for configuring cache expiry.</param> /// <param name="cancellationToken">A cancellation token to cancel running tasks with.</param> /// <returns>A boolean indicating whether the item was written to the cache or not.</returns> public static async Task <bool> SetAsync <T>( this IDistributedCache cache, string key, T value, IMethodCacheOptions methodCacheOptions = null, CancellationToken cancellationToken = default ) { byte[] cacheBytes; using (var memoryStream = new MemoryStream()) { await JsonSerializer.SerializeAsync(memoryStream, value, methodCacheOptions?.SerializeType ?? typeof(T), JsonSerializerOptions, cancellationToken); memoryStream.Position = 0; cacheBytes = memoryStream.ToArray(); } if (cacheBytes.Length == 0) { return(false); } var cacheEntryOptions = new DistributedCacheEntryOptions(); if (methodCacheOptions != null) { var expiration = new TimeSpan( methodCacheOptions.ExpirationHours, methodCacheOptions.ExpirationMinutes, methodCacheOptions.ExpirationSeconds ); if (expiration.Ticks > 0) { if (methodCacheOptions.SlidingExpiration) { cacheEntryOptions.SlidingExpiration = expiration; } else { cacheEntryOptions.AbsoluteExpirationRelativeToNow = expiration; } } } await cache.SetAsync( key, cacheBytes, cacheEntryOptions, cancellationToken ); return(true); }
/// <summary> /// Gets or creates a memory cache entry. /// </summary> /// <typeparam name="T">The result type.</typeparam> /// <param name="method">The method.</param> /// <param name="arguments">The method arguments.</param> /// <param name="methodCacheOptions">The <see cref="IMethodCacheOptions"/>.</param> /// <param name="factory">The result factory.</param> /// <returns>The existing or created memory cache entry value.</returns> public async Task <T> GetOrCreate <T>(MethodInfo method, object[] arguments, IMethodCacheOptions methodCacheOptions, Func <Task <T> > factory) { var invocationKey = await CacheKeyProvider.GetCacheKey(method, arguments); try { var cacheEntry = await DistributedCache.GetAsync <T>(invocationKey, methodCacheOptions.SerializeType); if (cacheEntry.Loaded) { return(cacheEntry.Value); } } catch (Exception ex) { Logger.LogError(ex, "Error while reading value with '{Key}' from distributed cache", invocationKey); } T value = await factory.Invoke(); var cacheSet = false; try { cacheSet = await DistributedCache.SetAsync(invocationKey, value, methodCacheOptions); } catch (Exception ex) { Logger.LogError(ex, "Error while writing value with key '{Key}' to distributed cache", invocationKey); } if (!cacheSet) { return(value); } await UpdateMethodKeys(invocationKey); return(value); }