ZiggyCreatures / FusionCache

FusionCache is an easy to use, fast and robust hybrid cache with advanced resiliency features.
MIT License
1.87k stars 96 forks source link

[BUG] IsFailSafeEnabled required to be set true in DefaultEntryOptions #333

Open waynebrantley opened 16 hours ago

waynebrantley commented 16 hours ago

@jodydonetti Really amazing work. So many features and all pretty simple to use.

It appears that if the DefaultEntryOptions do not turn on Fail Safe, it cannot be turned on. This fails for the 'false' case and succeeds for the 'true' case.

Is this expected behavior

    [TestCase(true)]
    [TestCase(false)]
    public void LocalFailSafeEnabled(bool setDefaultFailSafe)
    {
        var services = new ServiceCollection();
        services.AddMemoryCache();
        var cacheBuilder = services.AddFusionCache();
        cacheBuilder.WithDefaultEntryOptions(new FusionCacheEntryOptions
        {
            Duration = TimeSpan.FromHours(2), 
            IsFailSafeEnabled = setDefaultFailSafe,
            FailSafeMaxDuration = TimeSpan.FromDays(1), 
            FailSafeThrottleDuration = TimeSpan.FromSeconds(30),
            FactorySoftTimeout = TimeSpan.FromMilliseconds(100),
            FactoryHardTimeout = TimeSpan.FromMinutes(2),
        });

        var serviceProvider = services.BuildServiceProvider();
        var fusionCache = serviceProvider.GetRequiredService<IFusionCache>();

        var initialDateTime = fusionCache.GetOrSet("TEST",  _ =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(3));
            return DateTime.Now;
        }, options => options.SetDuration(TimeSpan.FromSeconds(30)).SetFailSafe(true, TimeSpan.FromHours(2), TimeSpan.FromSeconds(30)).SetFactoryTimeouts(TimeSpan.FromMilliseconds(100)));

        var cachedDateTime = fusionCache.GetOrSet("TEST",  _ =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(3));
            return DateTime.Now;
        }, options => options.SetDuration(TimeSpan.FromSeconds(30)).SetFailSafe(true, TimeSpan.FromHours(2), TimeSpan.FromSeconds(30)).SetFactoryTimeouts(TimeSpan.FromMilliseconds(100)));

        Assert.That(initialDateTime, Is.EqualTo(cachedDateTime));

        //now expire the cache
        fusionCache.Expire("TEST");
        var shouldUseExpiredValue = fusionCache.GetOrSet("TEST",  _ =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(3));
            return DateTime.Now;
        }, options => options.SetDuration(TimeSpan.FromSeconds(30)).SetFailSafe(true, TimeSpan.FromHours(2), TimeSpan.FromSeconds(30)).SetFactoryTimeouts(TimeSpan.FromMilliseconds(100)));

        Assert.That(shouldUseExpiredValue, Is.EqualTo(initialDateTime));

        Thread.Sleep(TimeSpan.FromSeconds(3)); //should be enough time for it to have finished

        var shouldBeNewValue = fusionCache.GetOrSet("TEST",  _ =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(3));
            return DateTime.Now;
        }, options => options.SetDuration(TimeSpan.FromSeconds(30)).SetFailSafe(true, TimeSpan.FromHours(2), TimeSpan.FromSeconds(30)).SetFactoryTimeouts(TimeSpan.FromMilliseconds(100)));

        Assert.That(shouldBeNewValue, Is.Not.EqualTo(initialDateTime));
    }