コード例 #1
0
        public async Task MemoryCacheLayer_CacheStack()
        {
            await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, null))
            {
                //Get 100 misses
                for (var i = 0; i < 100; i++)
                {
                    await cacheStack.GetAsync <int>("GetMiss_" + i);
                }

                var startDate = DateTime.UtcNow.AddDays(-50);

                //Set first 100 (simple type)
                for (var i = 0; i < 100; i++)
                {
                    await cacheStack.SetAsync("Comparison_" + i, new CacheEntry <int>(1, startDate.AddDays(i) + TimeSpan.FromDays(1)));
                }
                //Set last 100 (complex type)
                for (var i = 100; i < 200; i++)
                {
                    await cacheStack.SetAsync("Comparison_" + i, new CacheEntry <RealCostComplexType>(new RealCostComplexType
                    {
                        ExampleString = "Hello World",
                        ExampleNumber = 42,
                        ExampleDate = new DateTime(2000, 1, 1),
                        DictionaryOfNumbers = new Dictionary <string, int>()
                        {
                            { "A", 1 }, { "B", 2 }, { "C", 3 }
                        }
                    }, startDate.AddDays(i - 100) + TimeSpan.FromDays(1)));
                }

                //Get first 50 (simple type)
                for (var i = 0; i < 50; i++)
                {
                    await cacheStack.GetAsync <int>("Comparison_" + i);
                }
                //Get last 50 (complex type)
                for (var i = 150; i < 200; i++)
                {
                    await cacheStack.GetAsync <RealCostComplexType>("Comparison_" + i);
                }

                //Evict middle 100
                for (var i = 50; i < 150; i++)
                {
                    await cacheStack.EvictAsync("Comparison_" + i);
                }

                //Cleanup outer 100
                await cacheStack.CleanupAsync();
            }
        }
コード例 #2
0
        public async Task GetOrSet_ConcurrentStaleCacheHits_OnlyOneRefresh()
        {
            using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            var cacheEntry = new CacheEntry <int>(23, DateTime.UtcNow.AddDays(2));
            await cacheStack.SetAsync("GetOrSet_ConcurrentStaleCacheHits_OnlyOneRefresh", cacheEntry);

            Internal.DateTimeProvider.UpdateTime();

            var refreshWaitSource = new TaskCompletionSource <bool>();
            var getterCallCount   = 0;

            Parallel.For(0, 100, async v =>
            {
                await cacheStack.GetOrSetAsync <int>(
                    "GetOrSet_ConcurrentStaleCacheHits_OnlyOneRefresh",
                    async _ =>
                {
                    await Task.Delay(250);
                    Interlocked.Increment(ref getterCallCount);
                    refreshWaitSource.TrySetResult(true);
                    return(27);
                },
                    new CacheSettings(TimeSpan.FromDays(2), TimeSpan.Zero)
                    );
            });

            await Task.WhenAny(refreshWaitSource.Task, Task.Delay(TimeSpan.FromSeconds(5)));

            Assert.AreEqual(1, getterCallCount);
        }
コード例 #3
0
        public async Task GetOrSet_StaleCacheHit()
        {
            using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            var cacheEntry = new CacheEntry <int>(17, DateTime.UtcNow.AddDays(2));
            await cacheStack.SetAsync("GetOrSet_StaleCacheHit", cacheEntry);

            Internal.DateTimeProvider.UpdateTime();

            var refreshWaitSource = new TaskCompletionSource <bool>();

            var result = await cacheStack.GetOrSetAsync <int>("GetOrSet_StaleCacheHit", (oldValue) =>
            {
                Assert.AreEqual(17, oldValue);
                refreshWaitSource.TrySetResult(true);
                return(Task.FromResult(27));
            }, new CacheSettings(TimeSpan.FromDays(2), TimeSpan.Zero));

            Assert.AreEqual(17, result);

            await Task.WhenAny(refreshWaitSource.Task, Task.Delay(TimeSpan.FromSeconds(5)));

            var refetchedResult = await cacheStack.GetAsync <int>("GetOrSet_StaleCacheHit");

            Assert.AreEqual(27, refetchedResult.Value);
        }
コード例 #4
0
        public async Task GetOrSet_CacheHitBackgroundRefresh()
        {
            var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            var cacheEntry = new CacheEntry <int>(17, DateTime.UtcNow.AddDays(1));
            await cacheStack.SetAsync("GetOrSet_CacheHitBackgroundRefresh", cacheEntry);

            var waitingOnBackgroundTask = new TaskCompletionSource <int>();

            var result = await cacheStack.GetOrSetAsync <int>("GetOrSet_CacheHitBackgroundRefresh", (oldValue) =>
            {
                waitingOnBackgroundTask.TrySetResult(27);
                return(Task.FromResult(27));
            }, new CacheSettings(TimeSpan.FromDays(2), TimeSpan.Zero));

            Assert.AreEqual(17, result);

            await waitingOnBackgroundTask.Task;
            //Give 400ms to return the value and set it to the MemoryCacheLayer
            await Task.Delay(400);

            var refetchedResult = await cacheStack.GetAsync <int>("GetOrSet_CacheHitBackgroundRefresh");

            Assert.AreEqual(27, refetchedResult.Value);

            await DisposeOf(cacheStack);
        }
コード例 #5
0
        public async Task GetOrSet_ConcurrentStaleCacheHits()
        {
            await using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            var cacheEntry = new CacheEntry <int>(23, DateTime.UtcNow.AddDays(-2));
            await cacheStack.SetAsync("GetOrSet_ConcurrentStaleCacheHits", cacheEntry);

            var request1LockSource      = new TaskCompletionSource <bool>();
            var request2StartLockSource = new TaskCompletionSource <bool>();

            //Request 1 gets the lock on the refresh and ends up being tied up due to the TaskCompletionSource
            var request1Task = cacheStack.GetOrSetAsync <int>("GetOrSet_ConcurrentStaleCacheHits", async(oldValue) =>
            {
                request2StartLockSource.SetResult(true);
                await request1LockSource.Task;
                return(99);
            }, new CacheSettings(TimeSpan.FromDays(2), TimeSpan.Zero));

            await request2StartLockSource.Task;

            //Request 2 sees there is a lock already and because we still at least have old data, rather than wait
            //it is given the old cache data even though we are past the point where even stale data should be removed
            var request2Result = await cacheStack.GetOrSetAsync <int>("GetOrSet_ConcurrentStaleCacheHits", (oldValue) =>
            {
                return(Task.FromResult(99));
            }, new CacheSettings(TimeSpan.FromDays(2), TimeSpan.Zero));

            //Unlock Request 1 to to continue
            request1LockSource.SetResult(true);
            //Wait for Request 1 to complete so we get the new data
            var request1Result = await request1Task;

            Assert.AreEqual(99, request1Result);
            Assert.AreEqual(23, request2Result);
        }
コード例 #6
0
        public async Task Set_ThrowsOnUseAfterDisposal_CacheEntry()
        {
            var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, null);

            await DisposeOf(cacheStack);

            await cacheStack.SetAsync("KeyDoesntMatter", new CacheEntry <int>(1, TimeSpan.FromDays(1)));
        }
コード例 #7
0
        public async Task Set_ThrowsOnUseAfterDisposal()
        {
            var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, null);

            using (cacheStack) { }

            await cacheStack.SetAsync("KeyDoesntMatter", 1, TimeSpan.FromDays(1));
        }
コード例 #8
0
        public async Task Set_TriggersCacheChangeExtension()
        {
            var mockExtension = new Mock <ICacheChangeExtension>();

            using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, new[] { mockExtension.Object });
            var cacheEntry = await cacheStack.SetAsync("Set_TriggersCacheChangeExtension", 42, TimeSpan.FromDays(1));

            mockExtension.Verify(e => e.OnCacheUpdateAsync("Set_TriggersCacheChangeExtension", cacheEntry.Expiry), Times.Once);
        }
コード例 #9
0
 public async Task Set_TwoLayers()
 {
     await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer(), new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()))
     {
         for (var i = 0; i < WorkIterations; i++)
         {
             await cacheStack.SetAsync("Set", 15, TimeSpan.FromDays(1));
         }
     }
 }
コード例 #10
0
        public async Task Set_SetsAllTheLayers()
        {
            var layer1 = new MemoryCacheLayer();
            var layer2 = new MemoryCacheLayer();

            using var cacheStack = new CacheStack(new[] { layer1, layer2 }, Array.Empty <ICacheExtension>());
            var cacheEntry = await cacheStack.SetAsync("Set_SetsAllTheLayers", 42, TimeSpan.FromDays(1));

            Assert.AreEqual(cacheEntry, await layer1.GetAsync <int>("Set_SetsAllTheLayers"));
            Assert.AreEqual(cacheEntry, await layer2.GetAsync <int>("Set_SetsAllTheLayers"));
        }
コード例 #11
0
ファイル: CacheStackTests.cs プロジェクト: vp89/CacheTower
        public async Task Evict_TriggersCacheChangeExtension()
        {
            var mockExtension = new Mock <ICacheChangeExtension>();

            await using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, new [] { mockExtension.Object });
            var cacheEntry = await cacheStack.SetAsync("Evict_TriggerCacheChangeExtension", 42, TimeSpan.FromDays(1));

            await cacheStack.EvictAsync("Evict_TriggerCacheChangeExtension");

            mockExtension.Verify(e => e.OnCacheEvictionAsync("Evict_TriggerCacheChangeExtension"), Times.Once);
        }
コード例 #12
0
        public async Task GetHit()
        {
            await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()))
            {
                await cacheStack.SetAsync("GetHit", 15, TimeSpan.FromDays(1));

                for (var i = 0; i < WorkIterations; i++)
                {
                    await cacheStack.GetAsync <int>("GetHit");
                }
            }
        }
コード例 #13
0
        public async Task Cleanup()
        {
            await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()))
            {
                for (var i = 0; i < WorkIterations; i++)
                {
                    await cacheStack.SetAsync($"Cleanup_{i}", 15, TimeSpan.FromDays(1));
                }

                await cacheStack.CleanupAsync();
            }
        }
コード例 #14
0
        public async Task GetOrSet_CacheHit()
        {
            await using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            await cacheStack.SetAsync("GetOrSet_CacheHit", 17, TimeSpan.FromDays(2));

            var result = await cacheStack.GetOrSetAsync <int>("GetOrSet_CacheHit", (oldValue) =>
            {
                return(Task.FromResult(27));
            }, new CacheSettings(TimeSpan.FromDays(1)));

            Assert.AreEqual(17, result);
        }
コード例 #15
0
        public async Task GetOrSet_CacheHitButAllowedStalePoint()
        {
            await using var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
            var cacheEntry = new CacheEntry <int>(17, DateTime.UtcNow.AddDays(-1));
            await cacheStack.SetAsync("GetOrSet_CacheHitButAllowedStalePoint", cacheEntry);

            var result = await cacheStack.GetOrSetAsync <int>("GetOrSet_CacheHitButAllowedStalePoint", (oldValue) =>
            {
                return(Task.FromResult(27));
            }, new CacheSettings(TimeSpan.FromDays(1), TimeSpan.Zero));

            Assert.AreEqual(27, result);
        }
コード例 #16
0
 public async Task CacheTower_RedisCacheLayer()
 {
     await using (var cacheStack = new CacheStack(new[] { new RedisCacheLayer(RedisHelper.GetConnection()) }, Array.Empty <ICacheExtension>()))
     {
         await LoopActionAsync(Iterations, async() =>
         {
             await cacheStack.SetAsync("TestKey", 123, TimeSpan.FromDays(1));
             await cacheStack.GetAsync <int>("TestKey");
             await cacheStack.GetOrSetAsync <string>("GetOrSet_TestKey", (old) =>
             {
                 return(Task.FromResult("Hello World"));
             }, new CacheSettings(TimeSpan.FromDays(1), TimeSpan.FromDays(1)));
         });
     }
 }
コード例 #17
0
        public async Task GetOrSet_UnderLoad()
        {
            await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()))
            {
                await cacheStack.SetAsync("GetOrSet", new CacheEntry <int>(15, DateTime.UtcNow.AddDays(-1)));

                Parallel.For(0, WorkIterations, async value =>
                {
                    await cacheStack.GetOrSetAsync <int>("GetOrSet", async(old) =>
                    {
                        await Task.Delay(30);
                        return(12);
                    }, new CacheSettings(TimeSpan.FromDays(1)));
                });
            }
        }
コード例 #18
0
        public async Task Cleanup_CleansAllTheLayers()
        {
            var layer1 = new MemoryCacheLayer();
            var layer2 = new MemoryCacheLayer();

            using var cacheStack = new CacheStack(new[] { layer1, layer2 }, Array.Empty <ICacheExtension>());

            var cacheEntry = new CacheEntry <int>(42, DateTime.UtcNow.AddDays(-1));
            await cacheStack.SetAsync("Cleanup_CleansAllTheLayers", cacheEntry);

            Assert.AreEqual(cacheEntry, await layer1.GetAsync <int>("Cleanup_CleansAllTheLayers"));
            Assert.AreEqual(cacheEntry, await layer2.GetAsync <int>("Cleanup_CleansAllTheLayers"));

            await cacheStack.CleanupAsync();

            Assert.IsNull(await layer1.GetAsync <int>("Cleanup_CleansAllTheLayers"));
            Assert.IsNull(await layer2.GetAsync <int>("Cleanup_CleansAllTheLayers"));
        }
コード例 #19
0
        public async Task Evict_EvictsAllTheLayers()
        {
            var layer1 = new MemoryCacheLayer();
            var layer2 = new MemoryCacheLayer();

            var cacheStack = new CacheStack(new[] { layer1, layer2 }, Array.Empty <ICacheExtension>());
            var cacheEntry = await cacheStack.SetAsync("Evict_EvictsAllTheLayers", 42, TimeSpan.FromDays(1));

            Assert.AreEqual(cacheEntry, layer1.Get <int>("Evict_EvictsAllTheLayers"));
            Assert.AreEqual(cacheEntry, layer2.Get <int>("Evict_EvictsAllTheLayers"));

            await cacheStack.EvictAsync("Evict_EvictsAllTheLayers");

            Assert.IsNull(layer1.Get <int>("Evict_EvictsAllTheLayers"));
            Assert.IsNull(layer2.Get <int>("Evict_EvictsAllTheLayers"));

            await DisposeOf(cacheStack);
        }
コード例 #20
0
        public async Task GetOrSet_FourSimultaneous()
        {
            await using (var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>()))
            {
                await cacheStack.SetAsync("GetOrSet", new CacheEntry <int>(15, DateTime.UtcNow.AddDays(-1)));

                for (var i = 0; i < WorkIterations; i++)
                {
                    var task1 = cacheStack.GetOrSetAsync <int>("GetOrSet", async(old) =>
                    {
                        await Task.Delay(30);
                        return(12);
                    }, new CacheSettings(TimeSpan.FromDays(1)));
                    var task2 = cacheStack.GetOrSetAsync <int>("GetOrSet", async(old) =>
                    {
                        await Task.Delay(30);
                        return(12);
                    }, new CacheSettings(TimeSpan.FromDays(1)));
                    var task3 = cacheStack.GetOrSetAsync <int>("GetOrSet", async(old) =>
                    {
                        await Task.Delay(30);
                        return(12);
                    }, new CacheSettings(TimeSpan.FromDays(1)));
                    var task4 = cacheStack.GetOrSetAsync <int>("GetOrSet", async(old) =>
                    {
                        await Task.Delay(30);
                        return(12);
                    }, new CacheSettings(TimeSpan.FromDays(1)));

                    await task1;
                    await task2;
                    await task3;
                    await task4;
                }
            }
        }
コード例 #21
0
 public async Task Set_ThrowsOnNullCacheEntry()
 {
     var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
     await cacheStack.SetAsync("MyCacheKey", (CacheEntry <int>) null);
 }
コード例 #22
0
 public async Task Set_ThrowsOnNullKey()
 {
     var cacheStack = new CacheStack(new[] { new MemoryCacheLayer() }, Array.Empty <ICacheExtension>());
     await cacheStack.SetAsync(null, new CacheEntry <int>(1, TimeSpan.FromDays(1)));
 }