public void TryGet_ChecksLocalCacheThenDistributedCache()
        {
            var localCache       = new MockLocalCache <int, int>();
            var distributedCache = new MockDistributedCache <int, int>();

            var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default);

            for (var i = 1; i <= 100; i++)
            {
                twoTierCache.TryGet(i).Result.Success.Should().BeFalse();
                localCache.TryGetExecutionCount.Should().Be(i);
                distributedCache.TryGetExecutionCount.Should().Be(i);
            }

            for (var i = 1; i <= 100; i++)
            {
                twoTierCache.Set(i, i, TimeSpan.FromSeconds(1)).AsTask().Wait();
                localCache.SetExecutionCount.Should().Be(i);
                distributedCache.SetExecutionCount.Should().Be(i);
            }

            for (var i = 1; i <= 100; i++)
            {
                var(success, value, _) = twoTierCache.TryGet(i).Result;
                success.Should().BeTrue();
                value.Should().Be(i);

                localCache.TryGetExecutionCount.Should().Be(100 + i);
                distributedCache.TryGetExecutionCount.Should().Be(100);
            }
        }
        public void GetMany_SetsValueInLocalCacheIfFoundInDistributedCache()
        {
            var localCache       = new MockLocalCache <int, int>();
            var distributedCache = new MockDistributedCache <int, int>();

            var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default);

            distributedCache
            .SetMany(Enumerable.Range(0, 50).Select(i => new KeyValuePair <int, int>(i, i)).ToArray(), TimeSpan.FromSeconds(1))
            .Wait();

            distributedCache.SetManyExecutionCount.Should().Be(1);

            var values1 = twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result;

            values1.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50));

            localCache.GetManyExecutionCount.Should().Be(1);
            localCache.SetExecutionCount.Should().Be(50);
            distributedCache.GetManyExecutionCount.Should().Be(1);

            var values2 = twoTierCache.GetMany(Enumerable.Range(0, 50).ToArray()).Result;

            values2.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50));

            localCache.GetManyExecutionCount.Should().Be(2);
            distributedCache.GetManyExecutionCount.Should().Be(1);
        }
        public void TryGet_SetsValueInLocalCacheIfFoundInDistributedCache()
        {
            var localCache       = new MockLocalCache <int, int>();
            var distributedCache = new MockDistributedCache <int, int>();

            var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default);

            for (var i = 1; i <= 100; i++)
            {
                distributedCache.Set(i, i, TimeSpan.FromSeconds(100));
                distributedCache.SetExecutionCount.Should().Be(i);
            }

            for (var i = 1; i <= 100; i++)
            {
                var(success, value, _) = twoTierCache.TryGet(i).Result;
                success.Should().BeTrue();
                value.Should().Be(i);
                localCache.SetExecutionCount.Should().Be(i);
                localCache.TryGet(i, out var fromLocalCache).Should().BeTrue();
                fromLocalCache.Should().Be(i);
            }
        }
        public void GetMany_ChecksLocalCacheThenDistributedCache()
        {
            var localCache       = new MockLocalCache <int, int>();
            var distributedCache = new MockDistributedCache <int, int>();

            var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default);

            twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result.Should().BeEmpty();
            localCache.GetManyExecutionCount.Should().Be(1);
            distributedCache.GetManyExecutionCount.Should().Be(1);

            twoTierCache.SetMany(Enumerable.Range(0, 50).Select(i => new KeyValuePair <int, int>(i, i)).ToArray(), TimeSpan.FromSeconds(1));
            localCache.SetManyExecutionCount.Should().Be(1);
            distributedCache.SetManyExecutionCount.Should().Be(1);

            var results1 = twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result;

            results1.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50));
            foreach (var(key, value) in results1)
            {
                value.Should().Be(key);
            }
            localCache.GetManyExecutionCount.Should().Be(2);
            distributedCache.GetManyExecutionCount.Should().Be(2);

            var results2 = twoTierCache.GetMany(Enumerable.Range(0, 50).ToArray()).Result;

            results2.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50));
            foreach (var(key, value) in results2)
            {
                value.Should().Be(key);
            }

            localCache.GetManyExecutionCount.Should().Be(3);
            distributedCache.GetManyExecutionCount.Should().Be(2);
        }
        public void CacheStats_PopulatedCorrectly(bool localCacheEnabled, bool distributedCacheEnabled)
        {
            CacheGetStats lastCacheStats = default;

            Func <int, int> originalFunction = key => key;

            var config = CachedFunctionFactory.ConfigureFor(originalFunction)
                         .WithTimeToLive(TimeSpan.FromMinutes(1))
                         .OnResult(r => lastCacheStats = r.CacheStats)
                         .DontGetFromCacheWhen(k => k == 1)
                         .DontGetFromLocalCacheWhen(k => k == 2)
                         .DontGetFromDistributedCacheWhen(k => k == 3);

            if (localCacheEnabled)
            {
                var localCache = new MockLocalCache <int, int>();
                localCache.Set(4, 4, TimeSpan.FromMinutes(1));

                config.WithLocalCache(localCache);
            }

            if (distributedCacheEnabled)
            {
                var distributedCache = new MockDistributedCache <int, int>();
                distributedCache.Set(4, 4, TimeSpan.FromMinutes(1));
                distributedCache.Set(5, 5, TimeSpan.FromMinutes(1));

                config.WithDistributedCache(distributedCache);
            }

            var cachedFunction = config.Build();

            var cacheEnabled = localCacheEnabled || distributedCacheEnabled;

            for (var i = 1; i <= 5; i++)
            {
                cachedFunction(i).Should().Be(i);

                VerifyCacheStats(i);
            }

            void VerifyCacheStats(int key)
            {
                var localCacheKeyRequested = localCacheEnabled && key != 1 && key != 2;
                var localCacheHit          = localCacheEnabled && key == 4;

                var distributedCacheKeyRequested = distributedCacheEnabled && !localCacheHit && key != 1 && key != 3;
                var distributedCacheHit          = distributedCacheKeyRequested && (key == 4 || key == 5);

                var cacheKeyRequested = localCacheKeyRequested || distributedCacheKeyRequested;
                var cacheHit          = localCacheHit || distributedCacheHit;

                lastCacheStats.CacheEnabled.Should().Be(cacheEnabled);
                lastCacheStats.CacheKeyRequested.Should().Be(cacheKeyRequested);
                lastCacheStats.CacheSkipped.Should().Be(cacheEnabled && !cacheKeyRequested);
                lastCacheStats.CacheHit.Should().Be(cacheHit);
                lastCacheStats.CacheMiss.Should().Be(cacheKeyRequested && !cacheHit);

                lastCacheStats.LocalCacheEnabled.Should().Be(localCacheEnabled);
                lastCacheStats.LocalCacheKeyRequested.Should().Be(localCacheKeyRequested);
                lastCacheStats.LocalCacheSkipped.Should().Be(localCacheEnabled && !localCacheKeyRequested);
                lastCacheStats.LocalCacheHit.Should().Be(localCacheHit);
                lastCacheStats.LocalCacheMiss.Should().Be(localCacheKeyRequested && !localCacheHit);

                lastCacheStats.DistributedCacheEnabled.Should().Be(distributedCacheEnabled);
                lastCacheStats.DistributedCacheKeyRequested.Should().Be(distributedCacheKeyRequested);
                lastCacheStats.DistributedCacheSkipped.Should().Be(distributedCacheEnabled && !localCacheHit && !distributedCacheKeyRequested);
                lastCacheStats.DistributedCacheHit.Should().Be(distributedCacheHit);
                lastCacheStats.DistributedCacheMiss.Should().Be(distributedCacheKeyRequested && !distributedCacheHit);
            }
        }
        public void DontGetFromOrStoreInDistributedCacheWhen_ForSingleTierCache_WorksAsExpected(
            bool flag1, bool flag2, bool flag3, bool flag4)
        {
            Func <int, int> originalFunction = key => key;

            var cache = new MockDistributedCache <int, int>();

            var config = CachedFunctionFactory
                         .ConfigureFor(originalFunction)
                         .WithDistributedCache(cache)
                         .WithTimeToLive(TimeSpan.FromSeconds(1));

            if (flag1)
            {
                config.DontGetFromDistributedCacheWhen(key => key % 2 == 0);
            }

            if (flag2)
            {
                config.DontStoreInDistributedCacheWhen((key, _) => key % 3 == 0);
            }

            if (flag3)
            {
                config.DontGetFromDistributedCacheWhen(key => key % 5 == 0);
            }

            if (flag4)
            {
                config.DontStoreInDistributedCacheWhen((key, _) => key % 7 == 0);
            }

            var cachedFunction = config.Build();

            var previousTryGetExecutionCount = 0;
            var previousSetExecutionCount    = 0;

            for (var i = 0; i < 100; i++)
            {
                cachedFunction(i);

                var currentTryGetExecutionCount = cache.TryGetExecutionCount;
                var currentSetExecutionCount    = cache.SetExecutionCount;

                var skipGet = flag1 && i % 2 == 0 || flag3 && i % 5 == 0;
                var skipSet = flag2 && i % 3 == 0 || flag4 && i % 7 == 0;

                if (skipGet)
                {
                    currentTryGetExecutionCount.Should().Be(previousTryGetExecutionCount);
                }
                else
                {
                    currentTryGetExecutionCount.Should().Be(previousTryGetExecutionCount + 1);
                }

                if (skipSet)
                {
                    currentSetExecutionCount.Should().Be(previousSetExecutionCount);
                }
                else
                {
                    currentSetExecutionCount.Should().Be(previousSetExecutionCount + 1);
                }

                previousTryGetExecutionCount = currentTryGetExecutionCount;
                previousSetExecutionCount    = currentSetExecutionCount;
            }
        }
        public void DontGetFromOrStoreInLocalCacheWhen_DontGetFromOrStoreInDistributedCacheWhen_WorksAsExpected(
            bool flag1, bool flag2, bool flag3, bool flag4, bool flag5, bool flag6, bool flag7, bool flag8)
        {
            Func <int, int> originalFunction = key => key;

            var localCache       = new MockLocalCache <int, int>();
            var distributedCache = new MockDistributedCache <int, int>();

            var config = CachedFunctionFactory
                         .ConfigureFor(originalFunction)
                         .WithLocalCache(localCache)
                         .WithDistributedCache(distributedCache)
                         .WithTimeToLive(TimeSpan.FromSeconds(1));

            if (flag1)
            {
                config.DontGetFromLocalCacheWhen(key => key % 2 == 0);
            }

            if (flag2)
            {
                config.DontStoreInLocalCacheWhen((key, _) => key % 3 == 0);
            }

            if (flag3)
            {
                config.DontGetFromLocalCacheWhen(key => key % 5 == 0);
            }

            if (flag4)
            {
                config.DontStoreInLocalCacheWhen((key, _) => key % 7 == 0);
            }

            if (flag5)
            {
                config.DontGetFromDistributedCacheWhen(key => key % 11 == 0);
            }

            if (flag6)
            {
                config.DontStoreInDistributedCacheWhen((key, _) => key % 13 == 0);
            }

            if (flag7)
            {
                config.DontGetFromDistributedCacheWhen(key => key % 17 == 0);
            }

            if (flag8)
            {
                config.DontStoreInDistributedCacheWhen((key, _) => key % 19 == 0);
            }

            var cachedFunction = config.Build();

            var previousLocalTryGetExecutionCount       = 0;
            var previousLocalSetExecutionCount          = 0;
            var previousDistributedTryGetExecutionCount = 0;
            var previousDistributedSetExecutionCount    = 0;

            for (var i = 0; i < 100; i++)
            {
                cachedFunction(i);

                var currentLocalTryGetExecutionCount       = localCache.TryGetExecutionCount;
                var currentLocalSetExecutionCount          = localCache.SetExecutionCount;
                var currentDistributedTryGetExecutionCount = distributedCache.TryGetExecutionCount;
                var currentDistributedSetExecutionCount    = distributedCache.SetExecutionCount;

                var skipLocalGet       = flag1 && i % 2 == 0 || flag3 && i % 5 == 0;
                var skipLocalSet       = flag2 && i % 3 == 0 || flag4 && i % 7 == 0;
                var skipDistributedGet = flag5 && i % 11 == 0 || flag7 && i % 17 == 0;
                var skipDistributedSet = flag6 && i % 13 == 0 || flag8 && i % 19 == 0;

                if (skipLocalGet)
                {
                    currentLocalTryGetExecutionCount.Should().Be(previousLocalTryGetExecutionCount);
                }
                else
                {
                    currentLocalTryGetExecutionCount.Should().Be(previousLocalTryGetExecutionCount + 1);
                }

                if (skipLocalSet)
                {
                    currentLocalSetExecutionCount.Should().Be(previousLocalSetExecutionCount);
                }
                else
                {
                    currentLocalSetExecutionCount.Should().Be(previousLocalSetExecutionCount + 1);
                }

                if (skipDistributedGet)
                {
                    currentDistributedTryGetExecutionCount.Should().Be(previousDistributedTryGetExecutionCount);
                }
                else
                {
                    currentDistributedTryGetExecutionCount.Should().Be(previousDistributedTryGetExecutionCount + 1);
                }

                if (skipDistributedSet)
                {
                    currentDistributedSetExecutionCount.Should().Be(previousDistributedSetExecutionCount);
                }
                else
                {
                    currentDistributedSetExecutionCount.Should().Be(previousDistributedSetExecutionCount + 1);
                }

                previousLocalTryGetExecutionCount       = currentLocalTryGetExecutionCount;
                previousLocalSetExecutionCount          = currentLocalSetExecutionCount;
                previousDistributedTryGetExecutionCount = currentDistributedTryGetExecutionCount;
                previousDistributedSetExecutionCount    = currentDistributedSetExecutionCount;
            }
        }
Esempio n. 8
0
        public async Task TryRemove_EventsAreTriggeredSuccessfully(bool flag1, bool flag2)
        {
            var config = new DistributedCacheEventsWrapperConfig <int, int, int>();

            var successfulResults = new List <(int, int, bool, TimeSpan)>();
            var failedResults     = new List <(int, int, TimeSpan, Exception)>();

            if (flag1)
            {
                config.OnTryRemoveCompletedSuccessfully = (outerKey, innerKey, wasRemoved, duration) =>
                {
                    successfulResults.Add((outerKey, innerKey, wasRemoved, duration));
                };
            }

            if (flag2)
            {
                config.OnTryRemoveException = (outerKey, innerKey, duration, exception) =>
                {
                    failedResults.Add((outerKey, innerKey, duration, exception));
                    return(innerKey == 3);
                };
            }

            var innerCache = new MockDistributedCache <int, int, int>();
            var cache      = new DistributedCacheEventsWrapper <int, int, int>(config, innerCache);

            await cache.TryRemove(1, 1).ConfigureAwait(false);

            if (flag1)
            {
                successfulResults.Should().ContainSingle();
                successfulResults.Last().Item1.Should().Be(1);
                successfulResults.Last().Item2.Should().Be(1);
                successfulResults.Last().Item3.Should().BeFalse();
                successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                successfulResults.Should().BeEmpty();
            }

            await cache.Set(1, 2, 3, TimeSpan.FromSeconds(1)).ConfigureAwait(false);

            await cache.TryRemove(1, 2).ConfigureAwait(false);

            if (flag1)
            {
                successfulResults.Should().HaveCount(2);
                successfulResults.Last().Item1.Should().Be(1);
                successfulResults.Last().Item2.Should().Be(2);
                successfulResults.Last().Item3.Should().BeTrue();
                successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                successfulResults.Should().BeEmpty();
            }

            innerCache.ThrowExceptionOnNextAction();
            Func <Task> action = () => cache.TryRemove(1, 3);

            if (flag2)
            {
                await action().ConfigureAwait(false);

                failedResults.Should().ContainSingle();
                failedResults.Last().Item1.Should().Be(1);
                failedResults.Last().Item2.Should().Be(3);
                failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                await action.Should().ThrowAsync <Exception>().ConfigureAwait(false);

                failedResults.Should().BeEmpty();
            }
        }
Esempio n. 9
0
        public async Task GetMany_EventsAreTriggeredSuccessfully(bool flag1, bool flag2)
        {
            var config = new DistributedCacheEventsWrapperConfig <int, int, int>();

            var successfulResults = new List <(int, IReadOnlyCollection <int>, IReadOnlyCollection <KeyValuePair <int, ValueAndTimeToLive <int> > >, TimeSpan)>();
            var failedResults     = new List <(int, IReadOnlyCollection <int>, TimeSpan, Exception)>();

            if (flag1)
            {
                config.OnGetManyCompletedSuccessfully = (outerKey, innerKeys, values, duration) =>
                {
                    successfulResults.Add((outerKey, innerKeys, values, duration));
                };
            }

            if (flag2)
            {
                config.OnGetManyException = (outerKey, innerKeys, duration, exception) =>
                {
                    failedResults.Add((outerKey, innerKeys, duration, exception));
                    return(innerKeys.Contains(4));
                };
            }

            var innerCache = new MockDistributedCache <int, int, int>();
            var cache      = new DistributedCacheEventsWrapper <int, int, int>(config, innerCache);

            var innerKeys = new[] { 2, 3 };

            await cache.SetMany(1, new[] { new KeyValuePair <int, int>(2, 3) }, TimeSpan.FromSeconds(1)).ConfigureAwait(false);

            await cache.GetMany(1, innerKeys).ConfigureAwait(false);

            if (flag1)
            {
                successfulResults.Should().ContainSingle();
                successfulResults.Last().Item1.Should().Be(1);
                successfulResults.Last().Item2.Should().BeEquivalentTo(innerKeys);
                successfulResults.Last().Item3.ToArray().Select(kv => kv.Key).Should().BeEquivalentTo(2);
                successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                successfulResults.Should().BeEmpty();
            }

            innerCache.ThrowExceptionOnNextAction();
            Func <Task> action = () => cache.GetMany(1, innerKeys);
            await action.Should().ThrowAsync <Exception>().ConfigureAwait(false);

            if (flag2)
            {
                failedResults.Should().ContainSingle();
                failedResults.Last().Item1.Should().Be(1);
                failedResults.Last().Item2.Should().BeEquivalentTo(innerKeys);
                failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                failedResults.Should().BeEmpty();
            }

            innerKeys[1] = 4;

            innerCache.ThrowExceptionOnNextAction();
            action = () => cache.GetMany(1, innerKeys);
            if (flag2)
            {
                await action().ConfigureAwait(false);

                failedResults.Should().HaveCount(2);
                failedResults.Last().Item1.Should().Be(1);
                failedResults.Last().Item2.Should().BeEquivalentTo(innerKeys);
                failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                await action.Should().ThrowAsync <Exception>().ConfigureAwait(false);

                failedResults.Should().BeEmpty();
            }
        }
Esempio n. 10
0
        public async Task SetMany_EventsAreTriggeredSuccessfully(bool flag1, bool flag2)
        {
            var config = new DistributedCacheEventsWrapperConfig <int, int>();

            var successfulResults = new List <(IReadOnlyCollection <KeyValuePair <int, int> >, TimeSpan, TimeSpan)>();
            var failedResults     = new List <(IReadOnlyCollection <KeyValuePair <int, int> >, TimeSpan, TimeSpan, Exception)>();

            if (flag1)
            {
                config.OnSetManyCompletedSuccessfully = (values, timeToLive, duration) =>
                {
                    successfulResults.Add((values, timeToLive, duration));
                };
            }

            if (flag2)
            {
                config.OnSetManyException = (values, timeToLive, duration, exception) =>
                {
                    failedResults.Add((values, timeToLive, duration, exception));
                    return(values.Any(kv => kv.Key == 5));
                };
            }

            var innerCache = new MockDistributedCache <int, int>();
            var cache      = new DistributedCacheEventsWrapper <int, int>(config, innerCache);

            var values = new[] { new KeyValuePair <int, int>(1, 2), new KeyValuePair <int, int>(3, 4) };

            await cache.SetMany(values, TimeSpan.FromSeconds(1)).ConfigureAwait(false);

            if (flag1)
            {
                successfulResults.Should().ContainSingle();
                successfulResults.Last().Item1.Should().BeEquivalentTo(values);
                successfulResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1));
                successfulResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                successfulResults.Should().BeEmpty();
            }

            innerCache.ThrowExceptionOnNextAction();
            Func <Task> action = () => cache.SetMany(values, TimeSpan.FromSeconds(1));
            await action.Should().ThrowAsync <Exception>().ConfigureAwait(false);

            if (flag2)
            {
                failedResults.Should().ContainSingle();
                failedResults.Last().Item1.Should().BeEquivalentTo(values);
                failedResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1));
                failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                failedResults.Should().BeEmpty();
            }

            values[1] = new KeyValuePair <int, int>(5, 6);

            innerCache.ThrowExceptionOnNextAction();
            action = () => cache.SetMany(values, TimeSpan.FromSeconds(1));
            if (flag2)
            {
                await action().ConfigureAwait(false);

                failedResults.Should().HaveCount(2);
                failedResults.Last().Item1.Should().BeEquivalentTo(values);
                failedResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1));
                failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100));
            }
            else
            {
                await action.Should().ThrowAsync <Exception>().ConfigureAwait(false);

                failedResults.Should().BeEmpty();
            }
        }