public void DistributedCacheCircuitBreakerActuallyWorks() { var circuitBreakerDuration = TimeSpan.FromSeconds(2); var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions() { DistributedCacheCircuitBreakerDuration = circuitBreakerDuration }, memoryCache)) { fusionCache.DefaultEntryOptions.AllowBackgroundDistributedCacheOperations = false; fusionCache.SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer()); fusionCache.Set <int>("foo", 1, options => options.SetDurationSec(60).SetFailSafe(true)); chaosDistributedCache.SetAlwaysThrow(); fusionCache.Set <int>("foo", 2, options => options.SetDurationSec(60).SetFailSafe(true)); chaosDistributedCache.SetNeverThrow(); fusionCache.Set <int>("foo", 3, options => options.SetDurationSec(60).SetFailSafe(true)); Thread.Sleep(circuitBreakerDuration); memoryCache.Remove("foo"); var res = fusionCache.GetOrDefault <int>("foo", -1); Assert.Equal(1, res); } } }
public void FusionCacheCache() { using (var cache = new FusionCache(new FusionCacheOptions { DefaultEntryOptions = new FusionCacheEntryOptions(CacheDuration) })) { for (int i = 0; i < Rounds; i++) { FactoryCallsCount = 0; // FULL PARALLEL Parallel.ForEach(Keys, key => { Parallel.For(0, Accessors, _ => { cache.GetOrSet <long>( key, ct => { Interlocked.Increment(ref FactoryCallsCount); Thread.Sleep(FactoryDurationMs); return(DateTimeOffset.UtcNow.Ticks); } ); }); }); UpdateExcessiveFactoryCallsStatistics(GetCallerName(), KeysCount, FactoryCallsCount); } // NO NEED TO CLEANUP, AUTOMATICALLY DONE WHEN DISPOSING } }
public async Task OnlyOneFactoryGetsCalledEvenInHighConcurrencyAsync(int accessorsCount) { using (var cache = new FusionCache(new FusionCacheOptions())) { var factoryCallsCount = 0; var tasks = new ConcurrentBag <Task>(); Parallel.For(0, accessorsCount, _ => { var task = cache.GetOrSetAsync <int>( "foo", async _ => { Interlocked.Increment(ref factoryCallsCount); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10)) ); tasks.Add(task); }); await Task.WhenAll(tasks); Assert.Equal(1, factoryCallsCount); } }
public async Task DistributedCacheCircuitBreakerActuallyWorksAsync(SerializerType serializerType) { var circuitBreakerDuration = TimeSpan.FromSeconds(2); var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions() { DistributedCacheCircuitBreakerDuration = circuitBreakerDuration }, memoryCache)) { fusionCache.DefaultEntryOptions.AllowBackgroundDistributedCacheOperations = false; fusionCache.SetupDistributedCache(chaosDistributedCache, GetSerializer(serializerType)); await fusionCache.SetAsync <int>("foo", 1, options => options.SetDurationSec(60).SetFailSafe(true)); chaosDistributedCache.SetAlwaysThrow(); await fusionCache.SetAsync <int>("foo", 2, options => options.SetDurationSec(60).SetFailSafe(true)); chaosDistributedCache.SetNeverThrow(); await fusionCache.SetAsync <int>("foo", 3, options => options.SetDurationSec(60).SetFailSafe(true)); await Task.Delay(circuitBreakerDuration).ConfigureAwait(false); memoryCache.Remove("foo"); var res = await fusionCache.GetOrDefaultAsync <int>("foo", -1); Assert.Equal(1, res); } } }
public async Task FusionCache() { using (var cache = new FusionCache(new FusionCacheOptions { DefaultEntryOptions = new FusionCacheEntryOptions(CacheDuration) })) { for (int i = 0; i < Rounds; i++) { var tasks = new ConcurrentBag <Task>(); Parallel.ForEach(Keys, key => { Parallel.For(0, Accessors, _ => { var t = cache.GetOrSetAsync <SamplePayload>( key, async ct => { await Task.Delay(FactoryDurationMs).ConfigureAwait(false); return(new SamplePayload()); } ); tasks.Add(t); }); }); await Task.WhenAll(tasks).ConfigureAwait(false); } // NO NEED TO CLEANUP, AUTOMATICALLY DONE WHEN DISPOSING } }
public async Task AppliesDistributedCacheSoftTimeoutAsync() { var simulatedDelayMs = 5_000; var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); chaosDistributedCache.SetAlwaysDelayExactly(TimeSpan.FromMilliseconds(simulatedDelayMs)); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache)) { fusionCache.SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer()); await fusionCache.SetAsync <int>("foo", 42, new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true)); await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); var sw = Stopwatch.StartNew(); var res = await fusionCache.GetOrSetAsync <int>("foo", async ct => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true).SetDistributedCacheTimeouts(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1_000))); sw.Stop(); Assert.Equal(42, res); Assert.True(sw.ElapsedMilliseconds >= 100, "Distributed cache soft timeout not applied"); Assert.True(sw.ElapsedMilliseconds < simulatedDelayMs, "Distributed cache soft timeout not applied"); } } }
public async Task HandlesDistributedCacheFailuresInTheMiddleOfAnOperationAsync() { using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache).SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer())) { var task = fusionCache.GetOrSetAsync <int>("foo", async _ => { await Task.Delay(2_000); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10))); await Task.Delay(500); chaosDistributedCache.SetAlwaysThrow(); var value = await task; chaosDistributedCache.SetNeverThrow(); // END RESULT IS WHAT EXPECTED Assert.Equal(42, value); // MEMORY CACHE HAS BEEN UPDATED Assert.Equal(42, memoryCache.Get <FusionCacheEntry <int> >("foo").Value); // DISTRIBUTED CACHE HAS -NOT- BEEN UPDATED Assert.Null(distributedCache.GetString("foo")); } } }
public void FusionCache() { using (var cache = new FusionCache(new FusionCacheOptions { DefaultEntryOptions = new FusionCacheEntryOptions(CacheDuration) })) { for (int i = 0; i < Rounds; i++) { Parallel.ForEach(Keys, key => { Parallel.For(0, Accessors, _ => { cache.GetOrSet <SamplePayload>( key, ct => { Thread.Sleep(FactoryDurationMs); return(new SamplePayload()); } ); }); }); } // NO NEED TO CLEANUP, AUTOMATICALLY DONE WHEN DISPOSING } }
public void ThrowsOnFactoryHardTimeoutWithoutStaleData() { using (var cache = new FusionCache(new FusionCacheOptions())) { Assert.Throws <SyntheticTimeoutException>(() => { var value = cache.GetOrSet <int>("foo", _ => { Thread.Sleep(1_000); return(21); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true).SetFactoryTimeoutsMs(2_000, 100)); });
/// <summary> /// Adds the standard implementation of <see cref="IFusionCache"/> to the <see cref="IServiceCollection" />. /// </summary> /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param> /// <param name="setupOptionsAction">The <see cref="Action{FusionCacheOptions}"/> to configure the provided <see cref="FusionCacheOptions"/>.</param> /// <param name="useDistributedCacheIfAvailable">Automatically wires up an <see cref="IDistributedCache"/> if it has been registered in the Dependendy Injection container </param> /// <param name="ignoreMemoryDistributedCache">If the registered <see cref="IDistributedCache"/> found is an instance of <see cref="MemoryDistributedCache"/> (typical when using asp.net) it will be ignored, since it is completely useless (and will consume cpu and memory).</param> /// <param name="setupCacheAction">The <see cref="Action{IServiceProvider,FusionCacheOptions}"/> to configure the newly created <see cref="IFusionCache"/> instance.</param> /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns> public static IServiceCollection AddFusionCache(this IServiceCollection services, Action <FusionCacheOptions>?setupOptionsAction = null, bool useDistributedCacheIfAvailable = true, bool ignoreMemoryDistributedCache = true, Action <IServiceProvider, IFusionCache>?setupCacheAction = null) { if (services is null) { throw new ArgumentNullException(nameof(services)); } services.AddOptions(); if (setupOptionsAction is object) { services.Configure(setupOptionsAction); } services.TryAdd(ServiceDescriptor.Singleton <IFusionCache>(serviceProvider => { var logger = serviceProvider.GetService <ILogger <FusionCache> >(); var cache = new FusionCache( serviceProvider.GetRequiredService <IOptions <FusionCacheOptions> >(), serviceProvider.GetService <IMemoryCache>(), logger: logger ); if (useDistributedCacheIfAvailable) { var distributedCache = serviceProvider.GetService <IDistributedCache>(); if (ignoreMemoryDistributedCache && distributedCache is MemoryDistributedCache) { distributedCache = null; } if (distributedCache is object) { var serializer = serviceProvider.GetService <IFusionCacheSerializer>(); if (serializer is null) { if (logger?.IsEnabled(LogLevel.Warning) ?? false) { logger.LogWarning("FUSION: a usable implementation of IDistributedCache was found (CACHE={DistributedCacheType}) but no implementation of IFusionCacheSerializer was found, so the distributed cache subsystem has not been set up", distributedCache.GetType().FullName); } } else { cache.SetupDistributedCache(distributedCache, serializer); } } } setupCacheAction?.Invoke(serviceProvider, cache); return(cache); })); return(services); }
public async Task ThrowsOnFactoryHardTimeoutWithoutStaleDataAsync() { using (var cache = new FusionCache(new FusionCacheOptions())) { await Assert.ThrowsAsync <SyntheticTimeoutException>(async() => { var value = await cache.GetOrSetAsync <int>("foo", async _ => { await Task.Delay(1_000); return(21); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true).SetFactoryTimeoutsMs(2_000, 100)); }); } }
public void ReturnsStaleDataWhenFactoryFailsWithFailSafe() { using (var cache = new FusionCache(new FusionCacheOptions())) { var initialValue = cache.GetOrSet <int>("foo", _ => 42, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true)); Thread.Sleep(1_100); var newValue = cache.GetOrSet <int>("foo", _ => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true)); Assert.Equal(initialValue, newValue); } }
public async Task FusionCache_MemoryProviderAsync() { var fusionCache = new FusionCache(new FusionCacheOptions()); await LoopActionAsync(Iterations, async() => { await fusionCache.SetAsync("TestKey", 123, TimeSpan.FromDays(1)); await fusionCache.GetOrDefaultAsync <int>("TestKey"); await fusionCache.GetOrSetAsync("TestKey", (cancellationToken) => Task.FromResult("Hello World"), TimeSpan.FromDays(1)); }); }
public void FusionCache_MemoryProvider() { var fusionCache = new FusionCache(new FusionCacheOptions()); LoopAction(Iterations, () => { fusionCache.Set("TestKey", 123, TimeSpan.FromDays(1)); fusionCache.GetOrDefault <int>("TestKey"); fusionCache.GetOrSet("TestKey", (cancellationToken) => "Hello World", TimeSpan.FromDays(1)); }); }
public async Task ReturnsStaleDataWhenFactoryFailsWithFailSafeAsync() { using (var cache = new FusionCache(new FusionCacheOptions())) { var initialValue = await cache.GetOrSetAsync <int>("foo", async _ => 42, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true)); await Task.Delay(1_100); var newValue = await cache.GetOrSetAsync <int>("foo", async _ => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true)); Assert.Equal(initialValue, newValue); } }
public async Task ThrowsWhenFactoryThrowsWithoutFailSafeAsync() { using (var cache = new FusionCache(new FusionCacheOptions())) { var initialValue = await cache.GetOrSetAsync <int>("foo", async _ => 42, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(true)); await Task.Delay(1_100); await Assert.ThrowsAnyAsync <Exception>(async() => { var newValue = await cache.GetOrSetAsync <int>("foo", async _ => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)).SetFailSafe(false)); }); } }
public void HandlesFlexibleComplexTypeConversions(SerializerType serializerType) { using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache).SetupDistributedCache(distributedCache, GetSerializer(serializerType))) { var initialValue = (object)SampleComplexObject.CreateRandom(); fusionCache.Set("foo", initialValue, TimeSpan.FromHours(24)); memoryCache.Remove("foo"); var newValue = fusionCache.GetOrDefault <SampleComplexObject>("foo"); Assert.NotNull(newValue); } } }
public CacheAlternatives_Memory_Parallel_Benchmark() { CacheTower = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()); CacheManager = CacheFactory.Build <string>(b => { b.WithMicrosoftMemoryCacheHandle(); }); EasyCaching = new DefaultInMemoryCachingProvider( "EasyCaching", new[] { new InMemoryCaching("EasyCaching", new InMemoryCachingOptions()) }, new InMemoryOptions() ); LazyCache = new CachingService(); FusionCache = new FusionCache(new FusionCacheOptions()); }
public async Task HandlesDistributedCacheRemovalInTheMiddleOfAnOperationAsync() { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); using (var fusionCache = new FusionCache(new FusionCacheOptions()).SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer())) { var task = fusionCache.GetOrSetAsync <int>("foo", async _ => { await Task.Delay(2_000); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10))); await Task.Delay(500); fusionCache.RemoveDistributedCache(); var value = await task; Assert.Equal(42, value); } }
public async Task ReturnsDataFromDistributedCacheIfNoDataInMemoryCacheAsync() { using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache).SetupDistributedCache(distributedCache, new FusionCacheNewtonsoftJsonSerializer())) { var initialValue = await fusionCache.GetOrSetAsync <int>("foo", _ => Task.FromResult(42), new FusionCacheEntryOptions().SetDurationSec(10)); memoryCache.Remove("foo"); var newValue = await fusionCache.GetOrSetAsync <int>("foo", _ => Task.FromResult(21), new FusionCacheEntryOptions().SetDurationSec(10)); Assert.Equal(initialValue, newValue); } } }
public void ReturnsDataFromDistributedCacheIfNoDataInMemoryCache() { using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache).SetupDistributedCache(distributedCache, new FusionCacheNewtonsoftJsonSerializer())) { fusionCache.DefaultEntryOptions.AllowBackgroundDistributedCacheOperations = false; var initialValue = fusionCache.GetOrSet <int>("foo", _ => 42, options => options.SetDurationSec(10)); memoryCache.Remove("foo"); var newValue = fusionCache.GetOrSet <int>("foo", _ => 21, options => options.SetDurationSec(10)); Assert.Equal(initialValue, newValue); } } }
public async Task HandlesFlexibleSimpleTypeConversionsAsync(SerializerType serializerType) { using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache).SetupDistributedCache(distributedCache, GetSerializer(serializerType))) { var initialValue = (object)42; await fusionCache.SetAsync("foo", initialValue, TimeSpan.FromHours(24)); memoryCache.Remove("foo"); var newValue = await fusionCache.GetOrDefaultAsync <int>("foo"); Assert.Equal(initialValue, newValue); } } }
public void ThrowsWhenFactoryThrowsWithoutFailSafe() { using (var cache = new FusionCache(new FusionCacheOptions())) { var initialValue = cache.GetOrSet <int>("foo", _ => 42, new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)) { IsFailSafeEnabled = true }); Thread.Sleep(1_100); Assert.ThrowsAny <Exception>(() => { var newValue = cache.GetOrSet <int>("foo", _ => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)) { IsFailSafeEnabled = false }); }); } }
public async Task OnlyOneFactoryGetsCalledEvenInMixedHighConcurrencyAsync(int accessorsCount) { using (var cache = new FusionCache(new FusionCacheOptions())) { var factoryCallsCount = 0; var tasks = new ConcurrentBag <Task>(); Parallel.For(0, accessorsCount, idx => { if (idx % 2 == 0) { var task = cache.GetOrSetAsync <int>( "foo", async _ => { Interlocked.Increment(ref factoryCallsCount); await Task.Delay(FactoryDuration).ConfigureAwait(false); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10)) ); tasks.Add(task); } else { cache.GetOrSet <int>( "foo", _ => { Interlocked.Increment(ref factoryCallsCount); Thread.Sleep(FactoryDuration); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10)) ); } }); await Task.WhenAll(tasks); Assert.Equal(1, factoryCallsCount); } }
public async Task HandlesDistributedCacheFailuresAsync() { var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); using (var fusionCache = new FusionCache(new FusionCacheOptions()).SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer())) { var initialValue = await fusionCache.GetOrSetAsync <int>("foo", _ => Task.FromResult(42), new FusionCacheEntryOptions() { Duration = TimeSpan.FromSeconds(1), IsFailSafeEnabled = true }); await Task.Delay(1_500); chaosDistributedCache.SetAlwaysThrow(); var newValue = await fusionCache.GetOrSetAsync <int>("foo", async _ => throw new Exception("Generic error"), new FusionCacheEntryOptions(TimeSpan.FromSeconds(1)) { IsFailSafeEnabled = true });; Assert.Equal(initialValue, newValue); } }
public void AppliesDistributedCacheHardTimeout() { var simulatedDelayMs = 5_000; var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); chaosDistributedCache.SetAlwaysDelayExactly(TimeSpan.FromMilliseconds(simulatedDelayMs)); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache)) { fusionCache.SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer()); fusionCache.Set <int>("foo", 42, new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true)); Thread.Sleep(TimeSpan.FromSeconds(1)); memoryCache.Remove("foo"); Assert.Throws <Exception>(() => { _ = fusionCache.GetOrSet <int>("foo", ct => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true).SetDistributedCacheTimeouts(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1_000))); }); } } }
public void OnlyOneFactoryGetsCalledEvenInHighConcurrency(int accessorsCount) { using (var cache = new FusionCache(new FusionCacheOptions())) { var factoryCallsCount = 0; var tasks = new ConcurrentBag <Task>(); Parallel.For(0, accessorsCount, _ => { cache.GetOrSet <int>( "foo", _ => { Interlocked.Increment(ref factoryCallsCount); return(42); }, new FusionCacheEntryOptions(TimeSpan.FromSeconds(10)) ); }); Assert.Equal(1, factoryCallsCount); } }
public async Task FusionCacheCache() { using (var cache = new FusionCache(new FusionCacheOptions { DefaultEntryOptions = new FusionCacheEntryOptions(CacheDuration) })) { for (int i = 0; i < Rounds; i++) { var tasks = new ConcurrentBag <Task>(); FactoryCallsCount = 0; // FULL PARALLEL Parallel.ForEach(Keys, key => { Parallel.For(0, Accessors, _ => { var t = cache.GetOrSetAsync <long>( key, async ct => { Interlocked.Increment(ref FactoryCallsCount); await Task.Delay(FactoryDurationMs).ConfigureAwait(false); return(DateTimeOffset.UtcNow.Ticks); } ); tasks.Add(t); }); }); await Task.WhenAll(tasks).ConfigureAwait(false); UpdateExcessiveFactoryCallsStatistics(GetCallerName(), KeysCount, FactoryCallsCount); } // NO NEED TO CLEANUP, AUTOMATICALLY DONE WHEN DISPOSING } }
public void AppliesDistributedCacheSoftTimeout(SerializerType serializerType) { var simulatedDelayMs = 5_000; var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); chaosDistributedCache.SetAlwaysDelayExactly(TimeSpan.FromMilliseconds(simulatedDelayMs)); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache)) { fusionCache.SetupDistributedCache(chaosDistributedCache, GetSerializer(serializerType)); fusionCache.Set <int>("foo", 42, new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true)); Thread.Sleep(TimeSpan.FromSeconds(1)); var sw = Stopwatch.StartNew(); var res = fusionCache.GetOrSet <int>("foo", ct => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true).SetDistributedCacheTimeouts(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1_000))); sw.Stop(); Assert.Equal(42, res); Assert.True(sw.ElapsedMilliseconds >= 100, "Distributed cache soft timeout not applied"); Assert.True(sw.ElapsedMilliseconds < simulatedDelayMs, "Distributed cache soft timeout not applied"); } } }
public async Task AppliesDistributedCacheHardTimeoutAsync() { var simulatedDelayMs = 5_000; var distributedCache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); var chaosDistributedCache = new ChaosDistributedCache(distributedCache); chaosDistributedCache.SetAlwaysDelayExactly(TimeSpan.FromMilliseconds(simulatedDelayMs)); using (var memoryCache = new MemoryCache(new MemoryCacheOptions())) { using (var fusionCache = new FusionCache(new FusionCacheOptions(), memoryCache)) { fusionCache.SetupDistributedCache(chaosDistributedCache, new FusionCacheNewtonsoftJsonSerializer()); await fusionCache.SetAsync <int>("foo", 42, new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true)); await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); memoryCache.Remove("foo"); await Assert.ThrowsAsync <Exception>(async() => { var res = await fusionCache.GetOrSetAsync <int>("foo", async ct => throw new Exception("Sloths are cool"), new FusionCacheEntryOptions().SetDurationSec(1).SetFailSafe(true).SetDistributedCacheTimeouts(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(1_000))); }); } } }