diff --git a/CodeCoverage.runsettings b/CodeCoverage.runsettings
index 7e9d628c..754249ec 100644
--- a/CodeCoverage.runsettings
+++ b/CodeCoverage.runsettings
@@ -10,8 +10,10 @@
.*\.dll$
-
- CacheTower.Tests.dll
+
+ CacheTower.Tests.dll
+ CacheTower.Benchmarks.dll
+ CacheTower.AlternativesBenchmark.dll
diff --git a/docs/Comparison.md b/docs/Comparison.md
index 1aaa40e9..495fb9d2 100644
--- a/docs/Comparison.md
+++ b/docs/Comparison.md
@@ -12,77 +12,78 @@ If you are one of the maintainers of the libraries referenced below and you feel
**Test Machine**
```
-BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
+BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100
- [Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
- Core : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
+ [Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
+ Job-CQNZSR : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
-Job=Core Runtime=Core
+Runtime=.NET Core 3.0 MaxIterationCount=200
+UnrollFactor=1
```
## Memory Caching
| Method | Iterations | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------------------ |----------- |-------------------:|-----------------:|-----------------:|---------:|--------:|-----------:|-----------:|------:|-----------:|
-| CacheTower_MemoryCacheLayer_Direct | 1 | 758.2 ns | 12.00 ns | 11.22 ns | 0.32 | 0.00 | 0.1631 | - | - | 512 B |
-| LazyCache_MemoryProvider | 1 | 1,698.7 ns | 17.63 ns | 16.49 ns | 0.72 | 0.01 | 0.4139 | - | - | 1304 B |
-| LazyCache_MemoryProviderAsync | 1 | 1,984.2 ns | 38.70 ns | 30.21 ns | 0.84 | 0.02 | 0.4845 | - | - | 1520 B |
-| CacheTower_MemoryCacheLayer_ViaCacheStack | 1 | 2,355.6 ns | 23.82 ns | 21.12 ns | 1.00 | 0.00 | 0.3548 | - | - | 1120 B |
-| EasyCaching_InMemory | 1 | 9,869.4 ns | 133.65 ns | 125.02 ns | 4.19 | 0.06 | 1.3580 | - | - | 4281 B |
-| CacheManager_MicrosoftMemoryCache | 1 | 18,324.3 ns | 201.38 ns | 188.37 ns | 7.78 | 0.12 | 2.4719 | 1.2207 | - | 7848 B |
-| EasyCaching_InMemoryAsync | 1 | 23,729.5 ns | 466.39 ns | 555.21 ns | 10.08 | 0.26 | 2.0142 | - | - | 6257 B |
-| Akavache_InMemory | 1 | 1,297,026.2 ns | 10,505.78 ns | 9,827.12 ns | 550.27 | 4.88 | 19.5313 | 9.7656 | - | 66232 B |
+| CacheTower_MemoryCacheLayer_Direct | 1 | 778.2 ns | 16.37 ns | 14.51 ns | 0.33 | 0.01 | 0.1574 | - | - | 496 B |
+| LazyCache_MemoryProvider | 1 | 1,747.6 ns | 31.36 ns | 29.34 ns | 0.73 | 0.01 | 0.4139 | - | - | 1304 B |
+| LazyCache_MemoryProviderAsync | 1 | 2,048.3 ns | 11.69 ns | 10.36 ns | 0.86 | 0.01 | 0.4845 | - | - | 1520 B |
+| CacheTower_MemoryCacheLayer_ViaCacheStack | 1 | 2,392.3 ns | 22.62 ns | 18.89 ns | 1.00 | 0.00 | 0.3510 | - | - | 1104 B |
+| EasyCaching_InMemory | 1 | 9,788.1 ns | 139.27 ns | 130.28 ns | 4.09 | 0.07 | 1.3580 | - | - | 4281 B |
+| CacheManager_MicrosoftMemoryCache | 1 | 18,617.1 ns | 172.65 ns | 161.50 ns | 7.77 | 0.08 | 2.4719 | 1.2207 | - | 7848 B |
+| EasyCaching_InMemoryAsync | 1 | 25,383.4 ns | 503.14 ns | 654.23 ns | 10.70 | 0.28 | 2.0142 | - | - | 6260 B |
+| Akavache_InMemory | 1 | 1,316,664.7 ns | 11,369.24 ns | 10,634.80 ns | 550.04 | 7.27 | 19.5313 | 9.7656 | - | 66232 B |
| | | | | | | | | | | |
-| CacheTower_MemoryCacheLayer_Direct | 100 | 38,767.1 ns | 446.65 ns | 417.80 ns | 0.44 | 0.01 | 1.4038 | - | - | 4472 B |
-| CacheTower_MemoryCacheLayer_ViaCacheStack | 100 | 87,286.9 ns | 1,434.07 ns | 1,341.43 ns | 1.00 | 0.00 | 4.8828 | - | - | 15376 B |
-| LazyCache_MemoryProvider | 100 | 168,978.2 ns | 2,303.73 ns | 2,154.91 ns | 1.94 | 0.03 | 33.9355 | - | - | 106642 B |
-| LazyCache_MemoryProviderAsync | 100 | 189,229.9 ns | 2,746.71 ns | 2,293.63 ns | 2.17 | 0.04 | 40.7715 | - | - | 128240 B |
-| CacheManager_MicrosoftMemoryCache | 100 | 196,564.2 ns | 3,686.03 ns | 3,447.91 ns | 2.25 | 0.06 | 10.9863 | 3.6621 | - | 34790 B |
-| EasyCaching_InMemory | 100 | 451,180.2 ns | 6,187.16 ns | 5,166.56 ns | 5.18 | 0.09 | 35.6445 | - | - | 112806 B |
-| EasyCaching_InMemoryAsync | 100 | 913,772.6 ns | 17,705.40 ns | 17,389.07 ns | 10.46 | 0.25 | 66.4063 | - | - | 210705 B |
-| Akavache_InMemory | 100 | 128,480,626.8 ns | 1,157,242.01 ns | 1,025,864.90 ns | 1,474.27 | 22.51 | 2000.0000 | 1000.0000 | - | 6576334 B |
+| CacheTower_MemoryCacheLayer_Direct | 100 | 39,798.7 ns | 425.38 ns | 377.09 ns | 0.44 | 0.01 | 1.1597 | - | - | 3664 B |
+| CacheTower_MemoryCacheLayer_ViaCacheStack | 100 | 90,246.3 ns | 1,062.95 ns | 994.28 ns | 1.00 | 0.00 | 4.6387 | - | - | 14570 B |
+| LazyCache_MemoryProvider | 100 | 172,256.9 ns | 2,014.73 ns | 1,884.58 ns | 1.91 | 0.02 | 33.9355 | - | - | 106641 B |
+| LazyCache_MemoryProviderAsync | 100 | 191,666.9 ns | 1,486.80 ns | 1,390.75 ns | 2.12 | 0.02 | 40.7715 | - | - | 128240 B |
+| CacheManager_MicrosoftMemoryCache | 100 | 204,438.9 ns | 3,591.56 ns | 3,359.54 ns | 2.27 | 0.05 | 10.9863 | 3.6621 | - | 34790 B |
+| EasyCaching_InMemory | 100 | 452,204.4 ns | 4,000.21 ns | 3,741.80 ns | 5.01 | 0.07 | 35.6445 | - | - | 112806 B |
+| EasyCaching_InMemoryAsync | 100 | 903,208.0 ns | 17,237.22 ns | 18,443.63 ns | 10.01 | 0.25 | 66.4063 | - | - | 210689 B |
+| Akavache_InMemory | 100 | 131,507,873.3 ns | 1,732,164.29 ns | 1,620,267.55 ns | 1,457.31 | 19.56 | 2000.0000 | 1000.0000 | - | 6577278 B |
| | | | | | | | | | | |
-| CacheTower_MemoryCacheLayer_Direct | 1000 | 398,735.8 ns | 1,764.86 ns | 1,564.50 ns | 0.46 | 0.00 | 12.6953 | - | - | 40473 B |
-| CacheTower_MemoryCacheLayer_ViaCacheStack | 1000 | 873,629.7 ns | 3,261.48 ns | 2,891.22 ns | 1.00 | 0.00 | 45.8984 | - | - | 144976 B |
-| LazyCache_MemoryProvider | 1000 | 1,684,822.1 ns | 25,771.86 ns | 24,107.01 ns | 1.93 | 0.03 | 337.8906 | - | - | 1064243 B |
-| CacheManager_MicrosoftMemoryCache | 1000 | 1,809,405.6 ns | 25,329.40 ns | 23,693.13 ns | 2.07 | 0.03 | 87.8906 | - | - | 279715 B |
-| LazyCache_MemoryProviderAsync | 1000 | 1,856,364.0 ns | 27,768.92 ns | 25,975.07 ns | 2.12 | 0.03 | 406.2500 | - | - | 1280245 B |
-| EasyCaching_InMemory | 1000 | 4,388,849.5 ns | 54,388.28 ns | 50,874.83 ns | 5.03 | 0.05 | 343.7500 | - | - | 1099399 B |
-| EasyCaching_InMemoryAsync | 1000 | 8,220,673.5 ns | 102,349.65 ns | 95,737.93 ns | 9.41 | 0.12 | 656.2500 | - | - | 2068651 B |
-| Akavache_InMemory | 1000 | 1,327,851,400.0 ns | 13,538,489.80 ns | 12,663,911.76 ns | 1,520.00 | 14.80 | 20000.0000 | 10000.0000 | - | 65753656 B |
+| CacheTower_MemoryCacheLayer_Direct | 1000 | 405,720.8 ns | 7,902.60 ns | 8,115.39 ns | 0.45 | 0.01 | 10.2539 | - | - | 32464 B |
+| CacheTower_MemoryCacheLayer_ViaCacheStack | 1000 | 893,106.3 ns | 16,676.90 ns | 16,378.95 ns | 1.00 | 0.00 | 42.9688 | - | - | 136968 B |
+| LazyCache_MemoryProvider | 1000 | 1,830,634.8 ns | 35,334.35 ns | 37,807.36 ns | 2.05 | 0.04 | 337.8906 | - | - | 1064240 B |
+| CacheManager_MicrosoftMemoryCache | 1000 | 1,838,591.6 ns | 24,330.29 ns | 22,758.57 ns | 2.06 | 0.06 | 87.8906 | - | - | 279714 B |
+| LazyCache_MemoryProviderAsync | 1000 | 2,056,004.3 ns | 39,896.97 ns | 57,219.05 ns | 2.30 | 0.06 | 406.2500 | - | - | 1280241 B |
+| EasyCaching_InMemory | 1000 | 4,985,703.7 ns | 99,385.27 ns | 218,153.07 ns | 5.82 | 0.33 | 343.7500 | - | - | 1099395 B |
+| EasyCaching_InMemoryAsync | 1000 | 8,306,778.8 ns | 159,580.60 ns | 149,271.80 ns | 9.30 | 0.25 | 656.2500 | - | - | 2068651 B |
+| Akavache_InMemory | 1000 | 1,326,507,671.4 ns | 18,398,324.62 ns | 16,309,635.56 ns | 1,484.44 | 34.87 | 20000.0000 | 10000.0000 | - | 65745312 B |
## File Caching
| Method | Iterations | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------------------------- |----------- |-------------:|-----------:|-----------:|------:|--------:|-----------:|------:|------:|------------:|
-| EasyCaching_Disk | 1 | 4.367 ms | 0.1388 ms | 0.5799 ms | 0.73 | 0.13 | - | - | - | 37.96 KB |
-| CacheTower_ProtobufFileCacheLayer | 1 | 4.991 ms | 0.1752 ms | 0.7245 ms | 0.83 | 0.16 | - | - | - | 24.45 KB |
-| MonkeyCache_FileStore | 1 | 5.743 ms | 0.1617 ms | 0.6669 ms | 0.96 | 0.16 | - | - | - | 65.81 KB |
-| CacheTower_JsonFileCacheLayer | 1 | 6.071 ms | 0.1727 ms | 0.7181 ms | 1.00 | 0.00 | - | - | - | 55.5 KB |
+| EasyCaching_Disk | 1 | 4.466 ms | 0.1541 ms | 0.6508 ms | 0.73 | 0.14 | - | - | - | 38.03 KB |
+| CacheTower_ProtobufFileCacheLayer | 1 | 4.824 ms | 0.1557 ms | 0.6402 ms | 0.79 | 0.16 | - | - | - | 22.66 KB |
+| MonkeyCache_FileStore | 1 | 5.790 ms | 0.1885 ms | 0.7773 ms | 0.95 | 0.18 | - | - | - | 65.81 KB |
+| CacheTower_JsonFileCacheLayer | 1 | 6.180 ms | 0.2037 ms | 0.8353 ms | 1.00 | 0.00 | - | - | - | 54.63 KB |
| | | | | | | | | | | |
-| CacheTower_ProtobufFileCacheLayer | 100 | 93.950 ms | 1.8486 ms | 3.2859 ms | 0.71 | 0.03 | - | - | - | 1109.38 KB |
-| EasyCaching_Disk | 100 | 108.159 ms | 2.1508 ms | 5.4744 ms | 0.83 | 0.04 | - | - | - | 1766.05 KB |
-| CacheTower_JsonFileCacheLayer | 100 | 131.364 ms | 2.5835 ms | 5.0390 ms | 1.00 | 0.00 | - | - | - | 2779.68 KB |
-| MonkeyCache_FileStore | 100 | 186.004 ms | 3.4555 ms | 3.0632 ms | 1.40 | 0.05 | 1000.0000 | - | - | 4379.57 KB |
+| CacheTower_ProtobufFileCacheLayer | 100 | 96.250 ms | 1.9033 ms | 3.3830 ms | 0.71 | 0.03 | - | - | - | 1108.1 KB |
+| EasyCaching_Disk | 100 | 111.801 ms | 2.2223 ms | 5.1945 ms | 0.83 | 0.05 | - | - | - | 1766.05 KB |
+| CacheTower_JsonFileCacheLayer | 100 | 134.760 ms | 2.6579 ms | 5.9993 ms | 1.00 | 0.00 | - | - | - | 2776.66 KB |
+| MonkeyCache_FileStore | 100 | 189.205 ms | 3.6147 ms | 3.8677 ms | 1.39 | 0.08 | 1000.0000 | - | - | 4379.57 KB |
| | | | | | | | | | | |
-| CacheTower_ProtobufFileCacheLayer | 1000 | 890.211 ms | 16.0164 ms | 14.9817 ms | 0.72 | 0.01 | 3000.0000 | - | - | 10990.64 KB |
-| EasyCaching_Disk | 1000 | 1,042.211 ms | 15.8395 ms | 14.8162 ms | 0.84 | 0.01 | 5000.0000 | - | - | 17489.97 KB |
-| CacheTower_JsonFileCacheLayer | 1000 | 1,240.015 ms | 16.4974 ms | 15.4317 ms | 1.00 | 0.00 | 9000.0000 | - | - | 27566.44 KB |
-| MonkeyCache_FileStore | 1000 | 1,831.111 ms | 12.2941 ms | 11.4999 ms | 1.48 | 0.02 | 14000.0000 | - | - | 43596.71 KB |
+| CacheTower_ProtobufFileCacheLayer | 1000 | 896.184 ms | 17.0967 ms | 16.7913 ms | 0.71 | 0.02 | 3000.0000 | - | - | 10967.19 KB |
+| EasyCaching_Disk | 1000 | 1,084.950 ms | 21.6665 ms | 28.1726 ms | 0.85 | 0.02 | 5000.0000 | - | - | 17494.84 KB |
+| CacheTower_JsonFileCacheLayer | 1000 | 1,264.125 ms | 9.6589 ms | 8.5624 ms | 1.00 | 0.00 | 9000.0000 | - | - | 27543.12 KB |
+| MonkeyCache_FileStore | 1000 | 1,837.440 ms | 27.0019 ms | 25.2576 ms | 1.45 | 0.02 | 14000.0000 | - | - | 43596.71 KB |
## Redis Caching
| Method | Iterations | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------------------- |----------- |-----------:|----------:|----------:|-----------:|------:|--------:|----------:|------:|------:|-----------:|
-| CacheTower_RedisCacheLayer | 1 | 1.556 ms | 0.0737 ms | 0.3032 ms | 1.538 ms | 1.00 | 0.00 | - | - | - | 8.68 KB |
-| CacheManager_Redis | 1 | 2.671 ms | 0.1258 ms | 0.5229 ms | 2.595 ms | 1.78 | 0.53 | - | - | - | 27.32 KB |
-| EasyCaching_Redis | 1 | 4.185 ms | 0.1176 ms | 0.4849 ms | 4.137 ms | 2.80 | 0.67 | - | - | - | 508.97 KB |
+| CacheTower_RedisCacheLayer | 1 | 1.392 ms | 0.0824 ms | 0.3399 ms | 1.356 ms | 1.00 | 0.00 | - | - | - | 8.69 KB |
+| CacheManager_Redis | 1 | 2.441 ms | 0.1261 ms | 0.5270 ms | 2.445 ms | 1.86 | 0.61 | - | - | - | 27.34 KB |
+| EasyCaching_Redis | 1 | 3.752 ms | 0.1574 ms | 0.6597 ms | 3.628 ms | 2.85 | 0.84 | - | - | - | 509.45 KB |
| | | | | | | | | | | | |
-| EasyCaching_Redis | 100 | 42.269 ms | 0.8360 ms | 2.1280 ms | 41.626 ms | 1.03 | 0.06 | - | - | - | 851.64 KB |
-| CacheManager_Redis | 100 | 42.639 ms | 0.8600 ms | 2.7176 ms | 41.706 ms | 1.06 | 0.05 | - | - | - | 554.92 KB |
-| CacheTower_RedisCacheLayer | 100 | 43.361 ms | 1.9639 ms | 1.9288 ms | 42.616 ms | 1.00 | 0.00 | - | - | - | 475.92 KB |
+| CacheTower_RedisCacheLayer | 100 | 40.059 ms | 0.7942 ms | 2.3541 ms | 39.633 ms | 1.00 | 0.00 | - | - | - | 381.15 KB |
+| EasyCaching_Redis | 100 | 41.750 ms | 0.8300 ms | 2.0046 ms | 41.330 ms | 1.04 | 0.06 | - | - | - | 851.66 KB |
+| CacheManager_Redis | 100 | 46.709 ms | 0.9291 ms | 2.9088 ms | 46.250 ms | 1.17 | 0.08 | - | - | - | 554.92 KB |
| | | | | | | | | | | | |
-| CacheTower_RedisCacheLayer | 1000 | 376.746 ms | 4.1325 ms | 3.8655 ms | 377.178 ms | 1.00 | 0.00 | 1000.0000 | - | - | 3856.94 KB |
-| EasyCaching_Redis | 1000 | 379.035 ms | 3.7092 ms | 3.2881 ms | 379.064 ms | 1.01 | 0.01 | 1000.0000 | - | - | 3998.33 KB |
-| CacheManager_Redis | 1000 | 398.433 ms | 4.7762 ms | 4.4676 ms | 398.183 ms | 1.06 | 0.02 | 1000.0000 | - | - | 5351.58 KB |
\ No newline at end of file
+| CacheTower_RedisCacheLayer | 1000 | 379.765 ms | 8.7609 ms | 8.9968 ms | 376.901 ms | 1.00 | 0.00 | 1000.0000 | - | - | 3660.41 KB |
+| EasyCaching_Redis | 1000 | 385.377 ms | 7.1510 ms | 6.6891 ms | 385.932 ms | 1.01 | 0.03 | 1000.0000 | - | - | 3999.08 KB |
+| CacheManager_Redis | 1000 | 432.212 ms | 6.8948 ms | 6.4494 ms | 432.085 ms | 1.14 | 0.03 | 1000.0000 | - | - | 5352.86 KB |
\ No newline at end of file
diff --git a/docs/Performance.md b/docs/Performance.md
index f12a3a39..db77acf3 100644
--- a/docs/Performance.md
+++ b/docs/Performance.md
@@ -8,41 +8,42 @@ Regarding specific tests, it is best to look at the implementations themselves t
**Test Machine**
```
-BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
+BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100
- [Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
- Core : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
+ [Host] : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
+ Job-CQNZSR : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
-Job=Core Runtime=Core
+Runtime=.NET Core 3.0 MaxIterationCount=200
+UnrollFactor=1
```
## Cache Stack Benchmark
| Method | Mean [ns] | Error [ns] | StdDev [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
|-------------------------- |----------------:|--------------:|--------------:|-------:|------:|------:|--------------:|
-| SetupAndTeardown | 275.0 ns | 1.30 ns | 1.22 ns | 0.1326 | - | - | 416 B |
-| Set | 678.8 ns | 3.35 ns | 3.13 ns | 0.1879 | - | - | 592 B |
-| Set_TwoLayers | 773.4 ns | 2.06 ns | 1.93 ns | 0.2575 | - | - | 808 B |
-| Evict | 790.9 ns | 3.48 ns | 3.25 ns | 0.1879 | - | - | 592 B |
-| Evict_TwoLayers | 941.2 ns | 4.91 ns | 4.60 ns | 0.2575 | - | - | 808 B |
-| Cleanup | 974.4 ns | 7.65 ns | 7.16 ns | 0.1869 | - | - | 592 B |
-| Cleanup_TwoLayers | 1,208.6 ns | 4.53 ns | 3.54 ns | 0.2575 | - | - | 808 B |
-| GetMiss | 388.1 ns | 2.34 ns | 2.07 ns | 0.1326 | - | - | 416 B |
-| GetHit | 800.7 ns | 5.10 ns | 4.52 ns | 0.1879 | - | - | 592 B |
-| GetOrSet | 2,043.9 ns | 14.51 ns | 13.58 ns | 0.3357 | - | - | 1064 B |
-| GetOrSet_TwoSimultaneous | 62,232,054.8 ns | 329,492.60 ns | 308,207.58 ns | - | - | - | 3325 B |
-| GetOrSet_FourSimultaneous | 62,144,815.6 ns | 395,286.63 ns | 369,751.36 ns | - | - | - | 3677 B |
+| SetupAndTeardown | 269.3 ns | 4.63 ns | 4.11 ns | 0.1326 | - | - | 416 B |
+| Set | 661.3 ns | 6.44 ns | 5.38 ns | 0.1860 | - | - | 584 B |
+| Set_TwoLayers | 869.1 ns | 16.48 ns | 17.63 ns | 0.2975 | - | - | 936 B |
+| Evict | 799.2 ns | 14.25 ns | 13.33 ns | 0.1860 | - | - | 584 B |
+| Evict_TwoLayers | 1,030.8 ns | 14.00 ns | 13.09 ns | 0.2975 | - | - | 936 B |
+| Cleanup | 958.3 ns | 6.89 ns | 6.11 ns | 0.1850 | - | - | 584 B |
+| Cleanup_TwoLayers | 1,421.2 ns | 17.53 ns | 15.54 ns | 0.2975 | - | - | 936 B |
+| GetMiss | 375.4 ns | 3.88 ns | 3.63 ns | 0.1326 | - | - | 416 B |
+| GetHit | 793.1 ns | 12.73 ns | 11.91 ns | 0.1860 | - | - | 584 B |
+| GetOrSet | 1,916.0 ns | 21.73 ns | 18.15 ns | 0.3319 | - | - | 1048 B |
+| GetOrSet_TwoSimultaneous | 62,147,289.6 ns | 459,902.87 ns | 430,193.43 ns | - | - | - | 2322 B |
+| GetOrSet_FourSimultaneous | 62,142,030.0 ns | 393,933.53 ns | 368,485.67 ns | - | - | - | 2831 B |
## Cache Layer Comparison Benchmark
| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------- |-------------:|------------:|-------------:|-------------:|---------:|--------:|-----------:|------:|------:|------------:|
-| MemoryCacheLayer | 124.3 us | 1.40 us | 1.17 us | 124.7 us | 1.00 | 0.00 | 30.7617 | - | - | 94.34 KB |
-| RedisCacheLayer | 50,689.9 us | 1,008.28 us | 2,529.59 us | 49,719.1 us | 439.95 | 23.84 | - | - | - | 320.88 KB |
-| ProtobufFileCacheLayer | 214,656.5 us | 4,261.38 us | 7,001.57 us | 214,159.9 us | 1,753.22 | 63.32 | - | - | - | 1585.24 KB |
-| JsonFileCacheLayer | 262,911.9 us | 5,165.79 us | 9,182.18 us | 261,568.6 us | 2,103.16 | 74.19 | 1000.0000 | - | - | 3298.81 KB |
-| MongoDbCacheLayer | 466,444.2 us | 9,211.19 us | 20,024.37 us | 464,238.5 us | 3,859.08 | 207.18 | 11000.0000 | - | - | 33892.99 KB |
+| MemoryCacheLayer | 118.7 us | 2.26 us | 2.12 us | 118.4 us | 1.00 | 0.00 | 30.2734 | - | - | 92.77 KB |
+| RedisCacheLayer | 48,898.5 us | 970.75 us | 2,488.40 us | 47,959.8 us | 442.92 | 16.99 | - | - | - | 315.05 KB |
+| ProtobufFileCacheLayer | 225,156.9 us | 3,912.92 us | 3,468.70 us | 224,579.6 us | 1,896.36 | 47.60 | - | - | - | 1612.24 KB |
+| JsonFileCacheLayer | 279,037.0 us | 5,569.81 us | 11,869.73 us | 275,174.1 us | 2,450.32 | 112.80 | 1000.0000 | - | - | 3314.62 KB |
+| MongoDbCacheLayer | 484,883.7 us | 9,534.35 us | 19,901.73 us | 481,217.7 us | 4,177.79 | 176.27 | 10000.0000 | - | - | 30962.02 KB |
## In-Memory Benchmarks
@@ -50,53 +51,53 @@ Job=Core Runtime=Core
| Method | Mean [ns] | Error [ns] | StdDev [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
|------------ |------------:|-----------:|------------:|-------:|------:|------:|--------------:|
-| Overhead | 142.7 ns | 1.15 ns | 1.02 ns | 0.0663 | - | - | 208 B |
-| GetMiss | 208.5 ns | 1.99 ns | 1.77 ns | 0.0663 | - | - | 208 B |
-| GetHit | 533.8 ns | 3.10 ns | 2.90 ns | 0.1221 | - | - | 384 B |
-| SetNew | 448.7 ns | 3.02 ns | 2.83 ns | 0.1221 | - | - | 384 B |
-| SetExisting | 709.7 ns | 3.25 ns | 3.04 ns | 0.1345 | - | - | 424 B |
-| SetMany | 34,425.9 ns | 160.00 ns | 149.66 ns | 6.9580 | - | - | 21920 B |
+| Overhead | 135.1 ns | 1.09 ns | 0.97 ns | 0.0663 | - | - | 208 B |
+| GetMiss | 212.0 ns | 1.64 ns | 1.53 ns | 0.0663 | - | - | 208 B |
+| GetHit | 533.4 ns | 10.20 ns | 10.48 ns | 0.1192 | - | - | 376 B |
+| SetNew | 433.4 ns | 6.15 ns | 5.45 ns | 0.1197 | - | - | 376 B |
+| SetExisting | 745.5 ns | 10.43 ns | 9.24 ns | 0.1297 | - | - | 408 B |
+| SetMany | 33,831.8 ns | 483.94 ns | 429.00 ns | 6.7139 | - | - | 21120 B |
## File System Benchmarks
### FileCacheLayerBase (Overhead)
-| Method | Mean [ns] | Error [ns] | StdDev [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
-|------------------------ |----------------:|-------------:|---------------:|------:|------:|------:|--------------:|
-| GetHitSimultaneous | 2,341,841.8 ns | 76,116.2 ns | 318,943.0 ns | - | - | - | 16120 B |
-| SetExistingSimultaneous | 2,339,074.7 ns | 75,701.7 ns | 312,161.1 ns | - | - | - | 12664 B |
-| Overhead | 1,073,281.4 ns | 39,850.4 ns | 166,101.1 ns | - | - | - | 4560 B |
-| GetMiss | 1,482,845.9 ns | 50,339.9 ns | 209,822.5 ns | - | - | - | 7400 B |
-| GetHit | 2,113,604.9 ns | 58,434.3 ns | 237,663.9 ns | - | - | - | 13424 B |
-| SetNew | 1,957,598.5 ns | 59,701.2 ns | 249,502.0 ns | - | - | - | 9856 B |
-| SetExisting | 2,160,977.6 ns | 70,054.7 ns | 293,544.4 ns | - | - | - | 11704 B |
-| SetMany | 44,174,175.0 ns | 877,421.9 ns | 2,102,246.8 ns | - | - | - | 269352 B |
+| Method | Mean [ns] | Error [ns] | StdDev [ns] | Median [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
+|------------------------ |----------------:|-------------:|---------------:|----------------:|------:|------:|------:|--------------:|
+| GetHitSimultaneous | 2,239,577.2 ns | 67,345.3 ns | 276,948.1 ns | 2,202,500.0 ns | - | - | - | 16408 B |
+| SetExistingSimultaneous | 2,332,610.9 ns | 70,150.4 ns | 290,836.7 ns | 2,264,750.0 ns | - | - | - | 12792 B |
+| Overhead | 1,087,240.7 ns | 37,834.9 ns | 157,280.7 ns | 1,063,050.0 ns | - | - | - | 4560 B |
+| GetMiss | 1,445,024.1 ns | 45,014.7 ns | 184,102.9 ns | 1,423,500.0 ns | - | - | - | 7400 B |
+| GetHit | 2,091,793.5 ns | 53,136.4 ns | 219,705.9 ns | 2,050,550.0 ns | - | - | - | 13344 B |
+| SetNew | 1,918,547.1 ns | 53,247.8 ns | 217,774.8 ns | 1,889,100.0 ns | - | - | - | 9840 B |
+| SetExisting | 2,207,402.1 ns | 73,197.0 ns | 303,467.6 ns | 2,181,050.0 ns | - | - | - | 11520 B |
+| SetMany | 46,902,491.5 ns | 973,060.0 ns | 1,754,627.9 ns | 46,771,950.0 ns | - | - | - | 254400 B |
### JsonFileCacheLayer
| Method | Mean [ns] | Error [ns] | StdDev [ns] | Median [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
|------------------------ |----------------:|---------------:|---------------:|----------------:|------:|------:|------:|--------------:|
-| GetHitSimultaneous | 5,034,252.0 ns | 159,425.6 ns | 671,531.7 ns | 4,960,550.0 ns | - | - | - | 51816 B |
-| SetExistingSimultaneous | 5,403,373.1 ns | 174,596.2 ns | 733,517.1 ns | 5,318,100.0 ns | - | - | - | 51432 B |
-| Overhead | 1,668,915.7 ns | 55,233.5 ns | 232,048.2 ns | 1,618,800.0 ns | - | - | - | 12488 B |
-| GetMiss | 2,696,957.2 ns | 85,972.3 ns | 358,342.7 ns | 2,612,950.0 ns | - | - | - | 23816 B |
-| GetHit | 4,511,776.6 ns | 163,788.1 ns | 688,109.6 ns | 4,472,800.0 ns | - | - | - | 42816 B |
-| SetNew | 3,760,407.9 ns | 112,108.2 ns | 463,539.5 ns | 3,740,600.0 ns | - | - | - | 33568 B |
-| SetExisting | 4,620,312.1 ns | 155,706.6 ns | 655,866.8 ns | 4,574,850.0 ns | - | - | - | 42984 B |
-| SetMany | 90,178,101.8 ns | 1,798,547.6 ns | 3,909,894.4 ns | 89,256,200.0 ns | - | - | - | 1090800 B |
+| GetHitSimultaneous | 4,487,127.1 ns | 125,167.5 ns | 518,932.3 ns | 4,397,400.0 ns | - | - | - | 51928 B |
+| SetExistingSimultaneous | 4,983,330.6 ns | 123,043.3 ns | 511,494.1 ns | 4,892,300.0 ns | - | - | - | 51440 B |
+| Overhead | 1,644,103.4 ns | 48,518.2 ns | 200,610.7 ns | 1,613,850.0 ns | - | - | - | 12488 B |
+| GetMiss | 2,583,441.9 ns | 78,073.1 ns | 322,812.8 ns | 2,505,800.0 ns | - | - | - | 23656 B |
+| GetHit | 4,067,251.8 ns | 103,713.9 ns | 428,831.3 ns | 4,003,700.0 ns | - | - | - | 42720 B |
+| SetNew | 3,569,423.2 ns | 96,998.7 ns | 399,981.1 ns | 3,509,900.0 ns | - | - | - | 33480 B |
+| SetExisting | 4,229,421.4 ns | 109,822.2 ns | 455,312.2 ns | 4,148,700.0 ns | - | - | - | 42888 B |
+| SetMany | 92,741,550.0 ns | 1,837,211.9 ns | 3,217,728.5 ns | 92,088,850.0 ns | - | - | - | 1081200 B |
### ProtobufFileCacheLayer
-| Method | Mean [ns] | Error [ns] | StdDev [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
-|------------------------ |----------------:|---------------:|---------------:|------:|------:|------:|--------------:|
-| GetHitSimultaneous | 3,580,929.3 ns | 100,444.5 ns | 415,313.0 ns | - | - | - | 21304 B |
-| SetExistingSimultaneous | 3,978,112.4 ns | 112,489.1 ns | 467,620.1 ns | - | - | - | 21240 B |
-| Overhead | 1,269,990.8 ns | 49,961.3 ns | 209,348.7 ns | - | - | - | 4608 B |
-| GetMiss | 1,697,858.4 ns | 54,100.6 ns | 223,087.7 ns | - | - | - | 7440 B |
-| GetHit | 3,366,020.6 ns | 93,677.2 ns | 385,234.3 ns | - | - | - | 17768 B |
-| SetNew | 3,222,964.6 ns | 103,708.6 ns | 429,965.9 ns | - | - | - | 14040 B |
-| SetExisting | 3,634,562.3 ns | 114,139.8 ns | 471,939.9 ns | - | - | - | 17856 B |
-| SetMany | 62,429,050.0 ns | 1,259,236.3 ns | 2,365,151.0 ns | - | - | - | 490696 B |
+| Method | Mean [ns] | Error [ns] | StdDev [ns] | Median [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
+|------------------------ |----------------:|---------------:|---------------:|----------------:|------:|------:|------:|--------------:|
+| GetHitSimultaneous | 3,116,055.4 ns | 67,536.2 ns | 275,448.7 ns | 3,052,450.0 ns | - | - | - | 21272 B |
+| SetExistingSimultaneous | 3,627,764.3 ns | 84,783.8 ns | 348,661.2 ns | 3,544,450.0 ns | - | - | - | 21208 B |
+| Overhead | 1,183,173.3 ns | 35,858.8 ns | 148,267.1 ns | 1,176,100.0 ns | - | - | - | 4608 B |
+| GetMiss | 1,562,540.4 ns | 48,793.1 ns | 202,834.2 ns | 1,524,000.0 ns | - | - | - | 7440 B |
+| GetHit | 3,108,708.2 ns | 95,251.7 ns | 398,074.3 ns | 2,997,200.0 ns | - | - | - | 17744 B |
+| SetNew | 2,895,570.7 ns | 82,929.6 ns | 340,103.9 ns | 2,814,650.0 ns | - | - | - | 14184 B |
+| SetExisting | 3,224,126.8 ns | 93,260.0 ns | 388,718.7 ns | 3,126,650.0 ns | - | - | - | 17976 B |
+| SetMany | 62,606,770.0 ns | 1,249,913.1 ns | 2,795,609.8 ns | 62,614,000.0 ns | - | - | - | 477120 B |
## Database Benchmarks
@@ -104,14 +105,14 @@ Job=Core Runtime=Core
| Method | Mean [ns] | Error [ns] | StdDev [ns] | Median [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
|------------------------ |-----------------:|---------------:|---------------:|-----------------:|----------:|------:|------:|--------------:|
-| GetHitSimultaneous | 70,652,243.9 ns | 1,847,772.3 ns | 7,783,178.4 ns | 69,219,350.0 ns | - | - | - | 277504 B |
-| SetExistingSimultaneous | 70,761,139.7 ns | 1,785,866.2 ns | 7,443,701.3 ns | 69,789,050.0 ns | - | - | - | 253016 B |
-| Overhead | 7,777.6 ns | 493.5 ns | 1,891.7 ns | 7,400.0 ns | - | - | - | 424 B |
-| GetMiss | 67,504,475.6 ns | 1,778,059.7 ns | 7,470,019.1 ns | 65,904,500.0 ns | - | - | - | 121680 B |
-| GetHit | 71,031,643.2 ns | 1,820,413.6 ns | 7,687,867.3 ns | 70,016,600.0 ns | - | - | - | 198000 B |
-| SetNew | 69,524,188.8 ns | 1,715,738.5 ns | 7,208,194.0 ns | 68,905,900.0 ns | - | - | - | 109984 B |
-| SetExisting | 70,536,871.4 ns | 1,895,253.2 ns | 7,941,517.9 ns | 68,789,700.0 ns | - | - | - | 181504 B |
-| SetMany | 128,326,730.3 ns | 2,562,373.3 ns | 7,514,997.3 ns | 127,383,300.0 ns | 2000.0000 | - | - | 7294544 B |
+| GetHitSimultaneous | 72,721,353.5 ns | 1,949,497.6 ns | 8,211,665.2 ns | 71,905,100.0 ns | - | - | - | 261544 B |
+| SetExistingSimultaneous | 70,983,916.3 ns | 2,088,962.4 ns | 8,753,201.0 ns | 69,894,400.0 ns | - | - | - | 210224 B |
+| Overhead | 6,833.7 ns | 794.4 ns | 3,026.2 ns | 5,900.0 ns | - | - | - | 424 B |
+| GetMiss | 67,859,459.3 ns | 1,720,821.5 ns | 7,172,587.1 ns | 66,883,550.0 ns | - | - | - | 121664 B |
+| GetHit | 69,726,953.5 ns | 1,907,277.3 ns | 8,033,824.9 ns | 68,625,600.0 ns | - | - | - | 182888 B |
+| SetNew | 69,912,851.0 ns | 1,938,316.5 ns | 8,079,132.0 ns | 68,548,250.0 ns | - | - | - | 95720 B |
+| SetExisting | 68,935,014.2 ns | 1,906,826.9 ns | 8,010,998.5 ns | 67,035,400.0 ns | - | - | - | 152976 B |
+| SetMany | 125,761,659.1 ns | 2,502,151.4 ns | 7,759,473.3 ns | 124,211,200.0 ns | 1000.0000 | - | - | 5867032 B |
## Other
@@ -119,15 +120,14 @@ Job=Core Runtime=Core
| Method | Mean [ns] | Error [ns] | StdDev [ns] | Median [ns] | Gen 0 | Gen 1 | Gen 2 | Allocated [B] |
|------------------------ |----------------:|-------------:|-------------:|----------------:|------:|------:|------:|--------------:|
-| GetHitSimultaneous | 689,292.9 ns | 28,848.7 ns | 117,005.6 ns | 683,250.0 ns | - | - | - | 3040 B |
-| SetExistingSimultaneous | 694,434.0 ns | 30,077.4 ns | 123,011.6 ns | 688,150.0 ns | - | - | - | 3232 B |
-| Overhead | 8,091.0 ns | 1,256.6 ns | 4,847.1 ns | 6,300.0 ns | - | - | - | 136 B |
-| GetMiss | 404,778.8 ns | 21,734.5 ns | 89,380.1 ns | 389,800.0 ns | - | - | - | 840 B |
-| GetHit | 663,348.3 ns | 22,604.0 ns | 90,642.7 ns | 658,800.0 ns | - | - | - | 2296 B |
-| SetNew | 424,456.9 ns | 24,487.5 ns | 100,426.2 ns | 400,350.0 ns | - | - | - | 1304 B |
-| SetExisting | 694,905.3 ns | 28,549.4 ns | 117,084.4 ns | 684,850.0 ns | - | - | - | 2288 B |
-| SetMany | 13,767,330.3 ns | 268,302.3 ns | 985,616.9 ns | 13,577,950.0 ns | - | - | - | 97456 B |
-
+| GetHitSimultaneous | 543,613.0 ns | 32,141.7 ns | 133,256.3 ns | 519,700.0 ns | - | - | - | 3168 B |
+| SetExistingSimultaneous | 655,500.0 ns | 40,606.6 ns | 169,253.1 ns | 642,500.0 ns | - | - | - | 3184 B |
+| Overhead | 7,708.5 ns | 1,506.6 ns | 5,989.1 ns | 5,300.0 ns | - | - | - | 136 B |
+| GetMiss | 343,654.7 ns | 18,416.4 ns | 76,352.8 ns | 329,850.0 ns | - | - | - | 840 B |
+| GetHit | 582,914.5 ns | 23,003.7 ns | 93,821.2 ns | 574,150.0 ns | - | - | - | 2256 B |
+| SetNew | 387,381.4 ns | 19,223.8 ns | 78,186.9 ns | 382,050.0 ns | - | - | - | 1288 B |
+| SetExisting | 595,099.5 ns | 22,497.1 ns | 90,987.9 ns | 591,600.0 ns | - | - | - | 2256 B |
+| SetMany | 12,999,862.4 ns | 267,127.9 ns | 886,036.4 ns | 12,924,600.0 ns | - | - | - | 95832 B |
## Extensions
diff --git a/src/CacheTower.Extensions.Redis/RedisLockExtension.cs b/src/CacheTower.Extensions.Redis/RedisLockExtension.cs
index ff03ee67..75405713 100644
--- a/src/CacheTower.Extensions.Redis/RedisLockExtension.cs
+++ b/src/CacheTower.Extensions.Redis/RedisLockExtension.cs
@@ -90,7 +90,7 @@ private async Task> WaitForResult(string cacheKey, CacheSetting
//Last minute check to confirm whether waiting is required (in case the notification is missed)
var currentEntry = await RegisteredStack.GetAsync(cacheKey);
- if (currentEntry != null && !currentEntry.HasElapsed(settings.StaleAfter))
+ if (currentEntry != null && currentEntry.GetStaleDate(settings) > DateTime.UtcNow)
{
UnlockWaitingTasks(cacheKey);
return currentEntry;
diff --git a/src/CacheTower.Providers.Database.MongoDB/Commands/SetCommand.cs b/src/CacheTower.Providers.Database.MongoDB/Commands/SetCommand.cs
index 8be66f4d..4a89a5d1 100644
--- a/src/CacheTower.Providers.Database.MongoDB/Commands/SetCommand.cs
+++ b/src/CacheTower.Providers.Database.MongoDB/Commands/SetCommand.cs
@@ -23,8 +23,6 @@ public IEnumerable> GetModel()
var filter = Builders.Filter.Eq(e => e.CacheKey, Entry.CacheKey);
var updateDefinition = Builders.Update
.Set(e => e.CacheKey, Entry.CacheKey)
- .Set(e => e.CachedAt, Entry.CachedAt)
- .Set(e => e.TimeToLive, Entry.TimeToLive)
.Set(e => e.Expiry, Entry.Expiry)
.Set(e => e.Value, Entry.Value);
diff --git a/src/CacheTower.Providers.Database.MongoDB/Entities/DbCachedEntry.cs b/src/CacheTower.Providers.Database.MongoDB/Entities/DbCachedEntry.cs
index 604b87f2..2d0bbbff 100644
--- a/src/CacheTower.Providers.Database.MongoDB/Entities/DbCachedEntry.cs
+++ b/src/CacheTower.Providers.Database.MongoDB/Entities/DbCachedEntry.cs
@@ -14,15 +14,9 @@ public class DbCachedEntry
[Index(MongoFramework.IndexSortOrder.Ascending)]
public string CacheKey { get; set; }
- public DateTime CachedAt { get; set; }
- public TimeSpan TimeToLive { get; set; }
[Index(MongoFramework.IndexSortOrder.Ascending)]
- public DateTime Expiry
- {
- get => CachedAt + TimeToLive;
- set { }
- }
+ public DateTime Expiry { get; set; }
public object Value { get; set; }
}
diff --git a/src/CacheTower.Providers.Database.MongoDB/MongoDbCacheLayer.cs b/src/CacheTower.Providers.Database.MongoDB/MongoDbCacheLayer.cs
index 29008da6..1fe1574d 100644
--- a/src/CacheTower.Providers.Database.MongoDB/MongoDbCacheLayer.cs
+++ b/src/CacheTower.Providers.Database.MongoDB/MongoDbCacheLayer.cs
@@ -60,7 +60,7 @@ public async Task> GetAsync(string cacheKey)
if (dbEntry != default)
{
- cacheEntry = new CacheEntry((T)dbEntry.Value, dbEntry.CachedAt, dbEntry.TimeToLive);
+ cacheEntry = new CacheEntry((T)dbEntry.Value, dbEntry.Expiry);
}
return cacheEntry;
@@ -72,8 +72,7 @@ public async Task SetAsync(string cacheKey, CacheEntry cacheEntry)
var command = new SetCommand(new DbCachedEntry
{
CacheKey = cacheKey,
- CachedAt = cacheEntry.CachedAt,
- TimeToLive = cacheEntry.TimeToLive,
+ Expiry = cacheEntry.Expiry,
Value = cacheEntry.Value
});
diff --git a/src/CacheTower.Providers.FileSystem.Json/JsonFileCacheLayer.cs b/src/CacheTower.Providers.FileSystem.Json/JsonFileCacheLayer.cs
index b1476741..01228c99 100644
--- a/src/CacheTower.Providers.FileSystem.Json/JsonFileCacheLayer.cs
+++ b/src/CacheTower.Providers.FileSystem.Json/JsonFileCacheLayer.cs
@@ -14,11 +14,6 @@ public class JsonFileCacheLayer : FileCacheLayerBase, ICacheLayer
public JsonFileCacheLayer(string directoryPath) : base(directoryPath, ".json") { }
- private class DataWrapper
- {
- public T Value { get; set; }
- }
-
protected override T Deserialize(Stream stream)
{
using (var streamReader = new StreamReader(stream, Encoding.UTF8, false, 1024))
diff --git a/src/CacheTower.Providers.FileSystem.Protobuf/ProtobufManifestEntry.cs b/src/CacheTower.Providers.FileSystem.Protobuf/ProtobufManifestEntry.cs
index 466b6f88..064c1934 100644
--- a/src/CacheTower.Providers.FileSystem.Protobuf/ProtobufManifestEntry.cs
+++ b/src/CacheTower.Providers.FileSystem.Protobuf/ProtobufManifestEntry.cs
@@ -11,8 +11,6 @@ public class ProtobufManifestEntry : IManifestEntry
[ProtoMember(1)]
public string FileName { get; set; }
[ProtoMember(2)]
- public DateTime CachedAt { get; set; }
- [ProtoMember(3)]
- public TimeSpan TimeToLive { get; set; }
+ public DateTime Expiry { get; set; }
}
}
diff --git a/src/CacheTower.Providers.Redis/Entities/RedisCacheEntry.cs b/src/CacheTower.Providers.Redis/Entities/RedisCacheEntry.cs
index f3c5aa3b..bd0c93ca 100644
--- a/src/CacheTower.Providers.Redis/Entities/RedisCacheEntry.cs
+++ b/src/CacheTower.Providers.Redis/Entities/RedisCacheEntry.cs
@@ -9,10 +9,8 @@ namespace CacheTower.Providers.Redis.Entities
public class RedisCacheEntry
{
[ProtoMember(1)]
- public DateTime CachedAt { get; set; }
+ public DateTime Expiry { get; set; }
[ProtoMember(2)]
- public TimeSpan TimeToLive { get; set; }
- [ProtoMember(3)]
public T Value { get; set; }
}
}
diff --git a/src/CacheTower.Providers.Redis/RedisCacheLayer.cs b/src/CacheTower.Providers.Redis/RedisCacheLayer.cs
index 29501cda..38a149f4 100644
--- a/src/CacheTower.Providers.Redis/RedisCacheLayer.cs
+++ b/src/CacheTower.Providers.Redis/RedisCacheLayer.cs
@@ -12,7 +12,7 @@ public class RedisCacheLayer : IAsyncCacheLayer
private IDatabaseAsync Database { get; }
private bool? IsCacheAvailable { get; set; }
- public RedisCacheLayer(ConnectionMultiplexer connection, int databaseIndex = -1)
+ public RedisCacheLayer(IConnectionMultiplexer connection, int databaseIndex = -1)
{
Database = connection.GetDatabase(databaseIndex);
}
@@ -36,7 +36,7 @@ public async Task> GetAsync(string cacheKey)
using (var stream = new MemoryStream(redisValue))
{
var redisCacheEntry = Serializer.Deserialize>(stream);
- return new CacheEntry(redisCacheEntry.Value, redisCacheEntry.CachedAt, redisCacheEntry.TimeToLive);
+ return new CacheEntry(redisCacheEntry.Value, redisCacheEntry.Expiry);
}
}
@@ -63,17 +63,15 @@ public async Task IsAvailableAsync(string cacheKey)
public async Task SetAsync(string cacheKey, CacheEntry cacheEntry)
{
- //Redis doesn't support setting a TTL in the past, let's confirm the expiry date
- var trueTtl = (cacheEntry.CachedAt + cacheEntry.TimeToLive) - DateTime.UtcNow;
- if (trueTtl < TimeSpan.Zero)
+ var expiryOffset = cacheEntry.Expiry - DateTime.UtcNow;
+ if (expiryOffset < TimeSpan.Zero)
{
return;
}
var redisCacheEntry = new RedisCacheEntry
{
- CachedAt = cacheEntry.CachedAt,
- TimeToLive = cacheEntry.TimeToLive,
+ Expiry = cacheEntry.Expiry,
Value = cacheEntry.Value
};
@@ -83,7 +81,7 @@ public async Task SetAsync(string cacheKey, CacheEntry cacheEntry)
stream.Seek(0, SeekOrigin.Begin);
var redisValue = RedisValue.CreateFrom(stream);
- await Database.StringSetAsync(cacheKey, redisValue, cacheEntry.TimeToLive);
+ await Database.StringSetAsync(cacheKey, redisValue, expiryOffset);
}
}
}
diff --git a/src/CacheTower/CacheEntry.cs b/src/CacheTower/CacheEntry.cs
index 63b273b8..8722cde9 100644
--- a/src/CacheTower/CacheEntry.cs
+++ b/src/CacheTower/CacheEntry.cs
@@ -7,27 +7,20 @@ namespace CacheTower
{
public abstract class CacheEntry
{
- public DateTime CachedAt { get; }
+ public DateTime Expiry { get; }
- public TimeSpan TimeToLive { get; }
-
- protected CacheEntry(DateTime cachedAt, TimeSpan timeToLive)
+ protected CacheEntry(DateTime expiry)
{
- if (timeToLive < TimeSpan.Zero)
- {
- throw new ArgumentOutOfRangeException(nameof(timeToLive), "TimeSpan must be greater than or equal to zero");
- }
-
- CachedAt = new DateTime(
- cachedAt.Year, cachedAt.Month, cachedAt.Day, cachedAt.Hour, cachedAt.Minute, cachedAt.Second, DateTimeKind.Utc
+ //Force the resolution of the expiry date to be to the second
+ Expiry = new DateTime(
+ expiry.Year, expiry.Month, expiry.Day, expiry.Hour, expiry.Minute, expiry.Second, DateTimeKind.Utc
);
- TimeToLive = timeToLive;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool HasElapsed(TimeSpan timeSpan)
+ public DateTime GetStaleDate(CacheSettings cacheSettings)
{
- return CachedAt.Add(timeSpan) < DateTime.UtcNow;
+ return Expiry - cacheSettings.TimeToLive + cacheSettings.StaleAfter;
}
}
@@ -35,7 +28,8 @@ public class CacheEntry : CacheEntry, IEquatable>
{
public T Value { get; }
- public CacheEntry(T value, DateTime cachedAt, TimeSpan timeToLive) : base(cachedAt, timeToLive)
+ public CacheEntry(T value, TimeSpan timeToLive) : this(value, DateTime.UtcNow + timeToLive) { }
+ public CacheEntry(T value, DateTime expiry) : base(expiry)
{
Value = value;
}
@@ -48,8 +42,7 @@ public bool Equals(CacheEntry other)
}
return Equals(Value, other.Value) &&
- CachedAt == other.CachedAt &&
- TimeToLive == other.TimeToLive;
+ Expiry == other.Expiry;
}
public override bool Equals(object obj)
@@ -64,7 +57,7 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return (Value?.GetHashCode() ?? 1) ^ CachedAt.GetHashCode() ^ TimeToLive.GetHashCode();
+ return (Value?.GetHashCode() ?? 1) ^ Expiry.GetHashCode();
}
}
}
diff --git a/src/CacheTower/CacheStack.cs b/src/CacheTower/CacheStack.cs
index d48a697c..fa0a2ed5 100644
--- a/src/CacheTower/CacheStack.cs
+++ b/src/CacheTower/CacheStack.cs
@@ -97,7 +97,8 @@ public async ValueTask> SetAsync(string cacheKey, T value, Time
{
ThrowIfDisposed();
- var cacheEntry = new CacheEntry(value, DateTime.UtcNow, timeToLive);
+ var expiry = DateTime.UtcNow + timeToLive;
+ var cacheEntry = new CacheEntry(value, expiry);
await SetAsync(cacheKey, cacheEntry);
return cacheEntry;
}
@@ -222,10 +223,10 @@ public async ValueTask GetOrSetAsync(string cacheKey, Func> RefreshValueAsync(string cacheKey, Fun
//Last minute check to confirm whether waiting is required
var currentEntry = await GetAsync(cacheKey);
- if (currentEntry != null && !currentEntry.HasElapsed(settings.StaleAfter))
+ if (currentEntry != null && currentEntry.GetStaleDate(settings) > DateTime.UtcNow)
{
UnlockWaitingTasks(cacheKey);
return currentEntry;
diff --git a/src/CacheTower/Providers/FileSystem/FileCacheLayerBase.cs b/src/CacheTower/Providers/FileSystem/FileCacheLayerBase.cs
index 8528a14f..0c36e054 100644
--- a/src/CacheTower/Providers/FileSystem/FileCacheLayerBase.cs
+++ b/src/CacheTower/Providers/FileSystem/FileCacheLayerBase.cs
@@ -158,11 +158,11 @@ public async Task CleanupAsync()
{
await TryLoadManifestAsync();
+ var currentTime = DateTime.UtcNow;
foreach (var cachePair in CacheManifest)
{
var manifestEntry = cachePair.Value;
- var expiryDate = manifestEntry.CachedAt.Add(manifestEntry.TimeToLive);
- if (expiryDate < DateTime.UtcNow && CacheManifest.TryRemove(cachePair.Key, out var _))
+ if (manifestEntry.Expiry < currentTime && CacheManifest.TryRemove(cachePair.Key, out var _))
{
if (FileLock.TryRemove(manifestEntry.FileName, out var lockObj))
{
@@ -213,7 +213,7 @@ public async Task> GetAsync(string cacheKey)
{
var path = Path.Combine(DirectoryPath, manifestEntry.FileName);
var value = await DeserializeFileAsync(path);
- return new CacheEntry(value, manifestEntry.CachedAt, manifestEntry.TimeToLive);
+ return new CacheEntry(value, manifestEntry.Expiry);
}
}
}
@@ -248,9 +248,8 @@ public async Task SetAsync(string cacheKey, CacheEntry cacheEntry)
FileName = GetFileName(cacheKey)
});
- //Update the manifest entry with the new cache entry date/times
- manifestEntry.CachedAt = cacheEntry.CachedAt;
- manifestEntry.TimeToLive = cacheEntry.TimeToLive;
+ //Update the manifest entry with the new expiry
+ manifestEntry.Expiry = cacheEntry.Expiry;
var lockObj = FileLock.GetOrAdd(manifestEntry.FileName, (name) => new AsyncReaderWriterLock());
diff --git a/src/CacheTower/Providers/FileSystem/IManifestEntry.cs b/src/CacheTower/Providers/FileSystem/IManifestEntry.cs
index 7d71978b..ff8f6ccf 100644
--- a/src/CacheTower/Providers/FileSystem/IManifestEntry.cs
+++ b/src/CacheTower/Providers/FileSystem/IManifestEntry.cs
@@ -7,7 +7,6 @@ namespace CacheTower.Providers.FileSystem
public interface IManifestEntry
{
string FileName { get; set; }
- DateTime CachedAt { get; set; }
- TimeSpan TimeToLive { get; set; }
+ DateTime Expiry { get; set; }
}
}
diff --git a/src/CacheTower/Providers/FileSystem/ManifestEntry.cs b/src/CacheTower/Providers/FileSystem/ManifestEntry.cs
index d0ff7892..4dad243b 100644
--- a/src/CacheTower/Providers/FileSystem/ManifestEntry.cs
+++ b/src/CacheTower/Providers/FileSystem/ManifestEntry.cs
@@ -7,7 +7,6 @@ namespace CacheTower.Providers.FileSystem
public class ManifestEntry : IManifestEntry
{
public string FileName { get; set; }
- public DateTime CachedAt { get; set; }
- public TimeSpan TimeToLive { get; set; }
+ public DateTime Expiry { get; set; }
}
}
diff --git a/src/CacheTower/Providers/Memory/MemoryCacheLayer.cs b/src/CacheTower/Providers/Memory/MemoryCacheLayer.cs
index 24979410..ea15999d 100644
--- a/src/CacheTower/Providers/Memory/MemoryCacheLayer.cs
+++ b/src/CacheTower/Providers/Memory/MemoryCacheLayer.cs
@@ -22,11 +22,12 @@ public void Cleanup()
{
var keysToRemove = ArrayPool.Shared.Rent(Cache.Count);
var index = 0;
+ var currentTime = DateTime.UtcNow;
foreach (var cachePair in Cache)
{
var cacheEntry = cachePair.Value;
- if (cacheEntry.HasElapsed(cacheEntry.TimeToLive))
+ if (cacheEntry.Expiry < currentTime)
{
keysToRemove[index] = cachePair.Key;
index++;
diff --git a/tests/CacheTower.AlternativesBenchmark/CacheAlternatives_Memory_Benchmark.cs b/tests/CacheTower.AlternativesBenchmark/CacheAlternatives_Memory_Benchmark.cs
index 8dd74d27..c3d07b20 100644
--- a/tests/CacheTower.AlternativesBenchmark/CacheAlternatives_Memory_Benchmark.cs
+++ b/tests/CacheTower.AlternativesBenchmark/CacheAlternatives_Memory_Benchmark.cs
@@ -40,13 +40,13 @@ public void CacheTower_MemoryCacheLayer_Direct()
{
LoopAction(Iterations, () =>
{
- layer.Set("TestKey", new CacheEntry(123, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ layer.Set("TestKey", new CacheEntry(123, DateTime.UtcNow + TimeSpan.FromDays(1)));
layer.Get("TestKey");
var getOrSetResult = layer.Get("GetOrSet_TestKey");
if (getOrSetResult == null)
{
- layer.Set("GetOrSet_TestKey", new CacheEntry("Hello World", DateTime.UtcNow, TimeSpan.FromDays(1)));
+ layer.Set("GetOrSet_TestKey", new CacheEntry("Hello World", TimeSpan.FromDays(1)));
}
});
}
diff --git a/tests/CacheTower.Benchmarks/CacheStackBenchmark.cs b/tests/CacheTower.Benchmarks/CacheStackBenchmark.cs
index a7c146d4..47b34e34 100644
--- a/tests/CacheTower.Benchmarks/CacheStackBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/CacheStackBenchmark.cs
@@ -110,7 +110,7 @@ public async Task GetOrSet()
{
await using (var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty()))
{
- await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1)));
+ await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-1)));
await cacheStack.GetOrSetAsync("GetOrSet", (old, context) =>
{
return Task.FromResult(12);
@@ -122,7 +122,7 @@ public async Task GetOrSet_TwoSimultaneous()
{
await using (var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty()))
{
- await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1)));
+ await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-1)));
var task1 = cacheStack.GetOrSetAsync("GetOrSet", async (old, context) =>
{
await Task.Delay(50);
@@ -143,7 +143,7 @@ public async Task GetOrSet_FourSimultaneous()
{
await using (var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty()))
{
- await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1)));
+ await cacheStack.SetAsync("GetOrSet", new CacheEntry(15, DateTime.UtcNow.AddDays(-1)));
var task1 = cacheStack.GetOrSetAsync("GetOrSet", async (old, context) =>
{
await Task.Delay(50);
diff --git a/tests/CacheTower.Benchmarks/Extensions/BaseRefreshWrapperExtensionsBenchmark.cs b/tests/CacheTower.Benchmarks/Extensions/BaseRefreshWrapperExtensionsBenchmark.cs
index 3431b0a5..59fa2127 100644
--- a/tests/CacheTower.Benchmarks/Extensions/BaseRefreshWrapperExtensionsBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/Extensions/BaseRefreshWrapperExtensionsBenchmark.cs
@@ -15,7 +15,7 @@ public async Task RefreshValue()
extension.Register(CacheStack);
await extension.RefreshValueAsync("RefreshValue", () =>
{
- return new ValueTask>(new CacheEntry(5, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ return new ValueTask>(new CacheEntry(5, TimeSpan.FromDays(1)));
}, new CacheSettings(TimeSpan.FromDays(1)));
await DisposeOf(extension);
}
diff --git a/tests/CacheTower.Benchmarks/Providers/BaseAsyncCacheLayerBenchmark.cs b/tests/CacheTower.Benchmarks/Providers/BaseAsyncCacheLayerBenchmark.cs
index 1eec7ce5..dd9aa146 100644
--- a/tests/CacheTower.Benchmarks/Providers/BaseAsyncCacheLayerBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/Providers/BaseAsyncCacheLayerBenchmark.cs
@@ -13,7 +13,7 @@ public async Task GetHitSimultaneous()
{
var cacheLayer = CacheLayerProvider.Invoke() as IAsyncCacheLayer;
- await cacheLayer.SetAsync("GetHitSimultaneous", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await cacheLayer.SetAsync("GetHitSimultaneous", new CacheEntry(1, TimeSpan.FromDays(1)));
var aTask = cacheLayer.GetAsync("GetHitSimultaneous");
var bTask = cacheLayer.GetAsync("GetHitSimultaneous");
@@ -29,10 +29,10 @@ public async Task SetExistingSimultaneous()
{
var cacheLayer = CacheLayerProvider.Invoke() as IAsyncCacheLayer;
- await cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, TimeSpan.FromDays(1)));
- var aTask = cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
- var bTask = cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ var aTask = cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, TimeSpan.FromDays(1)));
+ var bTask = cacheLayer.SetAsync("SetExistingSimultaneous", new CacheEntry(1, TimeSpan.FromDays(1)));
await aTask;
await bTask;
diff --git a/tests/CacheTower.Benchmarks/Providers/BaseCacheLayerBenchmark.cs b/tests/CacheTower.Benchmarks/Providers/BaseCacheLayerBenchmark.cs
index 1d138629..09067f78 100644
--- a/tests/CacheTower.Benchmarks/Providers/BaseCacheLayerBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/Providers/BaseCacheLayerBenchmark.cs
@@ -68,12 +68,12 @@ public async Task GetHit()
var cacheLayer = CacheLayerProvider.Invoke();
if (cacheLayer is ISyncCacheLayer syncCacheLayer)
{
- syncCacheLayer.Set("GetHit", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ syncCacheLayer.Set("GetHit", new CacheEntry(1, TimeSpan.FromDays(1)));
syncCacheLayer.Get("GetHit");
}
else if (cacheLayer is IAsyncCacheLayer asyncLayer)
{
- await asyncLayer.SetAsync("GetHit", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await asyncLayer.SetAsync("GetHit", new CacheEntry(1, TimeSpan.FromDays(1)));
await asyncLayer.GetAsync("GetHit");
}
await DisposeOf(cacheLayer);
@@ -85,11 +85,11 @@ public async Task SetNew()
var cacheLayer = CacheLayerProvider.Invoke();
if (cacheLayer is ISyncCacheLayer syncCacheLayer)
{
- syncCacheLayer.Set("SetNew", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ syncCacheLayer.Set("SetNew", new CacheEntry(1, TimeSpan.FromDays(1)));
}
else if (cacheLayer is IAsyncCacheLayer asyncLayer)
{
- await asyncLayer.SetAsync("SetNew", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await asyncLayer.SetAsync("SetNew", new CacheEntry(1, TimeSpan.FromDays(1)));
}
await DisposeOf(cacheLayer);
}
@@ -99,13 +99,13 @@ public async Task SetExisting()
var cacheLayer = CacheLayerProvider.Invoke();
if (cacheLayer is ISyncCacheLayer syncCacheLayer)
{
- syncCacheLayer.Set("SetExisting", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
- syncCacheLayer.Set("SetExisting", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ syncCacheLayer.Set("SetExisting", new CacheEntry(1, TimeSpan.FromDays(1)));
+ syncCacheLayer.Set("SetExisting", new CacheEntry(1, TimeSpan.FromDays(1)));
}
else if (cacheLayer is IAsyncCacheLayer asyncLayer)
{
- await asyncLayer.SetAsync("SetExisting", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
- await asyncLayer.SetAsync("SetExisting", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await asyncLayer.SetAsync("SetExisting", new CacheEntry(1, TimeSpan.FromDays(1)));
+ await asyncLayer.SetAsync("SetExisting", new CacheEntry(1, TimeSpan.FromDays(1)));
}
await DisposeOf(cacheLayer);
}
@@ -118,14 +118,14 @@ public async Task SetMany()
{
for (var i = 0; i < 100; i++)
{
- syncCacheLayer.Set("SetMany_" + i, new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ syncCacheLayer.Set("SetMany_" + i, new CacheEntry(1, TimeSpan.FromDays(1)));
}
}
else if (cacheLayer is IAsyncCacheLayer asyncLayer)
{
for (var i = 0; i < 100; i++)
{
- await asyncLayer.SetAsync("SetMany_" + i, new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await asyncLayer.SetAsync("SetMany_" + i, new CacheEntry(1, TimeSpan.FromDays(1)));
}
}
await DisposeOf(cacheLayer);
diff --git a/tests/CacheTower.Benchmarks/Providers/CacheLayerComparisonBenchmark.cs b/tests/CacheTower.Benchmarks/Providers/CacheLayerComparisonBenchmark.cs
index 0ee39010..18efd605 100644
--- a/tests/CacheTower.Benchmarks/Providers/CacheLayerComparisonBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/Providers/CacheLayerComparisonBenchmark.cs
@@ -45,7 +45,7 @@ private void BenchmarkWork(ISyncCacheLayer cacheLayer)
//Set first 100 (simple type)
for (var i = 0; i < 100; i++)
{
- cacheLayer.Set("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i), TimeSpan.FromDays(1)));
+ cacheLayer.Set("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i) + TimeSpan.FromDays(1)));
}
//Set last 100 (complex type)
for (var i = 100; i < 200; i++)
@@ -56,7 +56,7 @@ private void BenchmarkWork(ISyncCacheLayer cacheLayer)
ExampleNumber = 42,
ExampleDate = new DateTime(2000, 1, 1),
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "B", 2 }, { "C", 3 } }
- }, startDate.AddDays(i - 100), TimeSpan.FromDays(1)));
+ }, startDate.AddDays(i - 100) + TimeSpan.FromDays(1)));
}
//Get first 50 (simple type)
@@ -92,7 +92,7 @@ private async Task BenchmarkWork(IAsyncCacheLayer cacheLayer)
//Set first 100 (simple type)
for (var i = 0; i < 100; i++)
{
- await cacheLayer.SetAsync("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i), TimeSpan.FromDays(1)));
+ await cacheLayer.SetAsync("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i) + TimeSpan.FromDays(1)));
}
//Set last 100 (complex type)
for (var i = 100; i < 200; i++)
@@ -103,7 +103,7 @@ private async Task BenchmarkWork(IAsyncCacheLayer cacheLayer)
ExampleNumber = 42,
ExampleDate = new DateTime(2000, 1, 1),
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "B", 2 }, { "C", 3 } }
- }, startDate.AddDays(i - 100), TimeSpan.FromDays(1)));
+ }, startDate.AddDays(i - 100) + TimeSpan.FromDays(1)));
}
//Get first 50 (simple type)
diff --git a/tests/CacheTower.Benchmarks/RealCostOfCacheStackBenchmark.cs b/tests/CacheTower.Benchmarks/RealCostOfCacheStackBenchmark.cs
index 78251d12..290d3659 100644
--- a/tests/CacheTower.Benchmarks/RealCostOfCacheStackBenchmark.cs
+++ b/tests/CacheTower.Benchmarks/RealCostOfCacheStackBenchmark.cs
@@ -36,7 +36,7 @@ public void MemoryCacheLayer_Independent()
//Set first 100 (simple type)
for (var i = 0; i < 100; i++)
{
- cacheLayer.Set("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i), TimeSpan.FromDays(1)));
+ cacheLayer.Set("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i) + TimeSpan.FromDays(1)));
}
//Set last 100 (complex type)
for (var i = 100; i < 200; i++)
@@ -47,7 +47,7 @@ public void MemoryCacheLayer_Independent()
ExampleNumber = 42,
ExampleDate = new DateTime(2000, 1, 1),
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "B", 2 }, { "C", 3 } }
- }, startDate.AddDays(i - 100), TimeSpan.FromDays(1)));
+ }, startDate.AddDays(i - 100) + TimeSpan.FromDays(1)));
}
//Get first 50 (simple type)
@@ -88,7 +88,7 @@ public async Task MemoryCacheLayer_CacheStack()
//Set first 100 (simple type)
for (var i = 0; i < 100; i++)
{
- await cacheStack.SetAsync("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i), TimeSpan.FromDays(1)));
+ await cacheStack.SetAsync("Comparison_" + i, new CacheEntry(1, startDate.AddDays(i) + TimeSpan.FromDays(1)));
}
//Set last 100 (complex type)
for (var i = 100; i < 200; i++)
@@ -99,7 +99,7 @@ public async Task MemoryCacheLayer_CacheStack()
ExampleNumber = 42,
ExampleDate = new DateTime(2000, 1, 1),
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "B", 2 }, { "C", 3 } }
- }, startDate.AddDays(i - 100), TimeSpan.FromDays(1)));
+ }, startDate.AddDays(i - 100) + TimeSpan.FromDays(1)));
}
//Get first 50 (simple type)
@@ -135,7 +135,7 @@ public void MemoryCacheLayer_Indepedent_GetOrSet()
var result = cacheLayer.Get("Comparison_" + i);
if (result == null)
{
- cacheLayer.Set("Comparison_" + i, new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ cacheLayer.Set("Comparison_" + i, new CacheEntry(1, TimeSpan.FromDays(1)));
}
}
@@ -151,7 +151,7 @@ public void MemoryCacheLayer_Indepedent_GetOrSet()
ExampleNumber = 42,
ExampleDate = new DateTime(2000, 1, 1),
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "B", 2 }, { "C", 3 } }
- }, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ }, TimeSpan.FromDays(1)));
}
}
}
diff --git a/tests/CacheTower.Tests/CacheEntryTests.cs b/tests/CacheTower.Tests/CacheEntryTests.cs
index 1e9177e3..f688bb02 100644
--- a/tests/CacheTower.Tests/CacheEntryTests.cs
+++ b/tests/CacheTower.Tests/CacheEntryTests.cs
@@ -10,61 +10,43 @@ namespace CacheTower.Tests
[TestClass]
public class CacheEntryTests
{
- [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void ThrowsExceptionOnNegativeTimeSpan()
- {
- new CacheEntry(0, DateTime.UtcNow, TimeSpan.FromSeconds(-1));
- }
-
[TestMethod]
- public void HasElapsed_NoOffset()
+ public void GetStaleDate()
{
- var entryInPast = new CacheEntry(0, DateTime.UtcNow.AddDays(-1), TimeSpan.Zero);
- Assert.IsTrue(entryInPast.HasElapsed(TimeSpan.Zero));
-
- var entryInFuture = new CacheEntry(0, DateTime.UtcNow.AddDays(1), TimeSpan.Zero);
- Assert.IsFalse(entryInFuture.HasElapsed(TimeSpan.Zero));
- }
-
- [TestMethod]
- public void HasElapsed_WithOffset()
- {
- var entryInPast1 = new CacheEntry(0, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1));
- Assert.IsTrue(entryInPast1.HasElapsed(TimeSpan.FromDays(1)));
-
- var entryInPast2 = new CacheEntry(0, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1));
- Assert.IsFalse(entryInPast2.HasElapsed(TimeSpan.FromDays(3)));
+ var expiry = DateTime.UtcNow;
+ var entry = new CacheEntry(0, expiry);
+ Assert.IsTrue(expiry - entry.GetStaleDate(new CacheSettings(TimeSpan.FromDays(3))) < TimeSpan.FromSeconds(1));
+ Assert.IsFalse(expiry - entry.GetStaleDate(new CacheSettings(TimeSpan.FromDays(3), TimeSpan.FromDays(2))) < TimeSpan.FromSeconds(1));
+ Assert.IsTrue(expiry.AddDays(-1) - entry.GetStaleDate(new CacheSettings(TimeSpan.FromDays(3), TimeSpan.FromDays(2))) < TimeSpan.FromSeconds(1));
}
[TestMethod]
public void EqualityTests_AreEqual()
{
var utcNow = DateTime.UtcNow;
- Assert.AreEqual(new CacheEntry(0, utcNow, TimeSpan.Zero), new CacheEntry(0, utcNow, TimeSpan.Zero));
- Assert.AreEqual(new CacheEntry(string.Empty, utcNow, TimeSpan.Zero), new CacheEntry(string.Empty, utcNow, TimeSpan.Zero));
+ Assert.AreEqual(new CacheEntry(0, utcNow), new CacheEntry(0, utcNow));
+ Assert.AreEqual(new CacheEntry(string.Empty, utcNow), new CacheEntry(string.Empty, utcNow));
}
[TestMethod]
public void EqualityTests_AreNotEqual()
{
var utcNow = DateTime.UtcNow;
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero), new CacheEntry(0, utcNow, TimeSpan.FromSeconds(1)));
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero), new CacheEntry(0, utcNow.AddDays(1), TimeSpan.Zero));
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero), new CacheEntry(1, utcNow, TimeSpan.Zero));
+ Assert.AreNotEqual(new CacheEntry(0, utcNow), new CacheEntry(0, utcNow.AddSeconds(1)));
+ Assert.AreNotEqual(new CacheEntry(0, utcNow), new CacheEntry(1, utcNow));
- Assert.IsFalse(new CacheEntry(0, utcNow, TimeSpan.Zero).Equals(null));
- Assert.IsFalse(new CacheEntry(0, utcNow, TimeSpan.Zero).Equals(string.Empty));
+ Assert.IsFalse(new CacheEntry(0, utcNow).Equals(null));
+ Assert.IsFalse(new CacheEntry(0, utcNow).Equals(string.Empty));
}
[TestMethod]
public void EqualityTests_HashCode()
{
var utcNow = DateTime.UtcNow;
- Assert.AreEqual(new CacheEntry(0, utcNow, TimeSpan.Zero).GetHashCode(), new CacheEntry(0, utcNow, TimeSpan.Zero).GetHashCode());
- Assert.AreEqual(new CacheEntry(string.Empty, utcNow, TimeSpan.Zero).GetHashCode(), new CacheEntry(string.Empty, utcNow, TimeSpan.Zero).GetHashCode());
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero).GetHashCode(), new CacheEntry(0, utcNow, TimeSpan.FromSeconds(1)).GetHashCode());
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero).GetHashCode(), new CacheEntry(0, utcNow.AddDays(1), TimeSpan.Zero).GetHashCode());
- Assert.AreNotEqual(new CacheEntry(0, utcNow, TimeSpan.Zero).GetHashCode(), new CacheEntry(1, utcNow, TimeSpan.Zero).GetHashCode());
+ Assert.AreEqual(new CacheEntry(0, utcNow).GetHashCode(), new CacheEntry(0, utcNow).GetHashCode());
+ Assert.AreEqual(new CacheEntry(string.Empty, utcNow).GetHashCode(), new CacheEntry(string.Empty, utcNow).GetHashCode());
+ Assert.AreNotEqual(new CacheEntry(0, utcNow).GetHashCode(), new CacheEntry(0, utcNow.AddSeconds(1)).GetHashCode());
+ Assert.AreNotEqual(new CacheEntry(0, utcNow).GetHashCode(), new CacheEntry(1, utcNow).GetHashCode());
}
}
}
diff --git a/tests/CacheTower.Tests/CacheStackTests.cs b/tests/CacheTower.Tests/CacheStackTests.cs
index 3364f079..50546b90 100644
--- a/tests/CacheTower.Tests/CacheStackTests.cs
+++ b/tests/CacheTower.Tests/CacheStackTests.cs
@@ -36,7 +36,7 @@ public async Task Cleanup_CleansAllTheLayers()
var cacheStack = new CacheStack(null, new[] { layer1, layer2 }, Array.Empty());
- var cacheEntry = new CacheEntry(42, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(42, DateTime.UtcNow.AddDays(-1));
await cacheStack.SetAsync("Cleanup_CleansAllTheLayers", cacheEntry);
Assert.AreEqual(cacheEntry, layer1.Get("Cleanup_CleansAllTheLayers"));
@@ -49,6 +49,14 @@ public async Task Cleanup_CleansAllTheLayers()
await DisposeOf(cacheStack);
}
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task Cleanup_ThrowsOnUseAfterDisposal()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+
+ await cacheStack.CleanupAsync();
+ }
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public async Task Evict_ThrowsOnNullKey()
@@ -56,7 +64,6 @@ public async Task Evict_ThrowsOnNullKey()
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
await cacheStack.EvictAsync(null);
}
-
[TestMethod]
public async Task Evict_EvictsAllTheLayers()
{
@@ -76,6 +83,14 @@ public async Task Evict_EvictsAllTheLayers()
await DisposeOf(cacheStack);
}
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task Evict_ThrowsOnUseAfterDisposal()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+
+ await cacheStack.EvictAsync("KeyDoesntMatter");
+ }
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public async Task Get_ThrowsOnNullKey()
@@ -83,12 +98,20 @@ public async Task Get_ThrowsOnNullKey()
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
await cacheStack.GetAsync(null);
}
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task Get_ThrowsOnUseAfterDisposal()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+
+ await cacheStack.GetAsync("KeyDoesntMatter");
+ }
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public async Task Set_ThrowsOnNullKey()
{
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
- await cacheStack.SetAsync(null, new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await cacheStack.SetAsync(null, new CacheEntry(1, TimeSpan.FromDays(1)));
}
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
@@ -97,7 +120,22 @@ public async Task Set_ThrowsOnNullCacheEntry()
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
await cacheStack.SetAsync("MyCacheKey", (CacheEntry)null);
}
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task Set_ThrowsOnUseAfterDisposal()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+
+ await cacheStack.SetAsync("KeyDoesntMatter", 1, TimeSpan.FromDays(1));
+ }
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task Set_ThrowsOnUseAfterDisposal_CacheEntry()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+ await cacheStack.SetAsync("KeyDoesntMatter", new CacheEntry(1, TimeSpan.FromDays(1)));
+ }
[TestMethod]
public async Task Set_SetsAllTheLayers()
{
@@ -119,14 +157,12 @@ public async Task GetOrSet_ThrowsOnNullKey()
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
await cacheStack.GetOrSetAsync(null, (old, context) => Task.FromResult(5), new CacheSettings(TimeSpan.FromDays(1)));
}
-
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public async Task GetOrSet_ThrowsOnNullGetter()
{
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
await cacheStack.GetOrSetAsync("MyCacheKey", null, new CacheSettings(TimeSpan.FromDays(1)));
}
-
[TestMethod]
public async Task GetOrSet_CacheMiss()
{
@@ -140,7 +176,6 @@ public async Task GetOrSet_CacheMiss()
await DisposeOf(cacheStack);
}
-
[TestMethod]
public async Task GetOrSet_CacheHit()
{
@@ -156,12 +191,11 @@ public async Task GetOrSet_CacheHit()
await DisposeOf(cacheStack);
}
-
[TestMethod]
public async Task GetOrSet_CacheHitBackgroundRefresh()
{
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
- var cacheEntry = new CacheEntry(17, DateTime.UtcNow.AddDays(-1), TimeSpan.FromDays(2));
+ var cacheEntry = new CacheEntry(17, DateTime.UtcNow.AddDays(1));
await cacheStack.SetAsync("GetOrSet_CacheHitBackgroundRefresh", cacheEntry);
var waitingOnBackgroundTask = new TaskCompletionSource();
@@ -182,7 +216,6 @@ public async Task GetOrSet_CacheHitBackgroundRefresh()
await DisposeOf(cacheStack);
}
-
[TestMethod]
public async Task GetOrSet_BackPropagatesToEarlierCacheLayers()
{
@@ -191,7 +224,7 @@ public async Task GetOrSet_BackPropagatesToEarlierCacheLayers()
var layer3 = new MemoryCacheLayer();
var cacheStack = new CacheStack(null, new[] { layer1, layer2, layer3 }, Array.Empty());
- var cacheEntry = new CacheEntry(42, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(42, TimeSpan.FromDays(1));
layer2.Set("GetOrSet_BackPropagatesToEarlierCacheLayers", cacheEntry);
var cacheEntryFromStack = await cacheStack.GetOrSetAsync("GetOrSet_BackPropagatesToEarlierCacheLayers", (old, context) =>
@@ -209,12 +242,11 @@ public async Task GetOrSet_BackPropagatesToEarlierCacheLayers()
await DisposeOf(cacheStack);
}
-
[TestMethod]
public async Task GetOrSet_CacheHitButAllowedStalePoint()
{
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
- var cacheEntry = new CacheEntry(17, DateTime.UtcNow.AddDays(-2), TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(17, DateTime.UtcNow.AddDays(-1));
await cacheStack.SetAsync("GetOrSet_CacheHitButAllowedStalePoint", cacheEntry);
var result = await cacheStack.GetOrSetAsync("GetOrSet_CacheHitButAllowedStalePoint", (oldValue, context) =>
@@ -225,12 +257,11 @@ public async Task GetOrSet_CacheHitButAllowedStalePoint()
await DisposeOf(cacheStack);
}
-
[TestMethod]
public async Task GetOrSet_ConcurrentStaleCacheHits()
{
var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, Array.Empty());
- var cacheEntry = new CacheEntry(23, DateTime.UtcNow.AddDays(-3), TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(23, DateTime.UtcNow.AddDays(-2));
await cacheStack.SetAsync("GetOrSet_ConcurrentStaleCacheHits", cacheEntry);
ValueTask DoRequest()
@@ -258,5 +289,13 @@ ValueTask DoRequest()
await DisposeOf(cacheStack);
}
+ [TestMethod, ExpectedException(typeof(ObjectDisposedException))]
+ public async Task GetOrSet_ThrowsOnUseAfterDisposal()
+ {
+ var cacheStack = new CacheStack(null, new[] { new MemoryCacheLayer() }, null);
+ await DisposeOf(cacheStack);
+
+ await cacheStack.GetOrSetAsync("KeyDoesntMatter", (old, context) => Task.FromResult(1), new CacheSettings(TimeSpan.FromDays(1)));
+ }
}
}
diff --git a/tests/CacheTower.Tests/Extensions/ExtensionContainerTests.cs b/tests/CacheTower.Tests/Extensions/ExtensionContainerTests.cs
index cf758774..c153fdda 100644
--- a/tests/CacheTower.Tests/Extensions/ExtensionContainerTests.cs
+++ b/tests/CacheTower.Tests/Extensions/ExtensionContainerTests.cs
@@ -35,7 +35,7 @@ public async Task RefreshWrapperExtension()
container.Register(cacheStackMock.Object);
- var cacheEntry = new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(1, TimeSpan.FromDays(1));
var refreshedValue = await container.RefreshValueAsync("WrapperTestCacheKey", () =>
{
diff --git a/tests/CacheTower.Tests/Extensions/Redis/RedisLockExtensionTests.cs b/tests/CacheTower.Tests/Extensions/Redis/RedisLockExtensionTests.cs
index 3c6b9f66..46400c54 100644
--- a/tests/CacheTower.Tests/Extensions/Redis/RedisLockExtensionTests.cs
+++ b/tests/CacheTower.Tests/Extensions/Redis/RedisLockExtensionTests.cs
@@ -52,7 +52,7 @@ public async Task CustomLockTimeout()
{
lockWaiterTask.SetResult(true);
await refreshWaiterTask.Task;
- return new CacheEntry(5, DateTime.UtcNow, TimeSpan.FromDays(1));
+ return new CacheEntry(5, TimeSpan.FromDays(1));
}, new CacheSettings(TimeSpan.FromHours(3)));
await lockWaiterTask.Task;
@@ -95,7 +95,7 @@ await connection.GetSubscriber().SubscribeAsync("CacheTower.CacheLock", (channel
var extension = new RedisLockExtension(connection);
extension.Register(cacheStackMock.Object);
- var cacheEntry = new CacheEntry(13, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(13, TimeSpan.FromDays(1));
await extension.RefreshValueAsync("TestKey",
() => new ValueTask>(cacheEntry), new CacheSettings(TimeSpan.FromDays(1)));
@@ -121,7 +121,7 @@ public async Task WaitingTaskInSameInstanceUnlocksAndCompletes()
var extension = new RedisLockExtension(connection);
extension.Register(cacheStackMock.Object);
- var cacheEntry = new CacheEntry(13, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(13, TimeSpan.FromDays(1));
var secondaryTaskKickoff = new TaskCompletionSource();
var primaryTask = extension.RefreshValueAsync("TestKey",
@@ -167,7 +167,7 @@ public async Task WaitingTaskInDifferentInstanceUnlocksAndCompletes()
var extensionTwo = new RedisLockExtension(connection);
extensionTwo.Register(cacheStackMockTwo.Object);
- var cacheEntry = new CacheEntry(13, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(13, TimeSpan.FromDays(1));
var secondaryTaskKickoff = new TaskCompletionSource();
var primaryTask = extensionOne.RefreshValueAsync("TestKey",
diff --git a/tests/CacheTower.Tests/Providers/BaseCacheLayerTests.cs b/tests/CacheTower.Tests/Providers/BaseCacheLayerTests.cs
index 8b3a42de..5730ce7c 100644
--- a/tests/CacheTower.Tests/Providers/BaseCacheLayerTests.cs
+++ b/tests/CacheTower.Tests/Providers/BaseCacheLayerTests.cs
@@ -13,7 +13,7 @@ public abstract class BaseCacheLayerTests : TestBase
{
protected static void AssertGetSetCache(ISyncCacheLayer cacheLayer)
{
- var cacheEntry = new CacheEntry(12, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(12, TimeSpan.FromDays(1));
cacheLayer.Set("AssertGetSetCache", cacheEntry);
var cacheEntryGet = cacheLayer.Get("AssertGetSetCache");
@@ -21,7 +21,7 @@ protected static void AssertGetSetCache(ISyncCacheLayer cacheLayer)
}
protected static async Task AssertGetSetCacheAsync(IAsyncCacheLayer cacheLayer)
{
- var cacheEntry = new CacheEntry(12, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(12, TimeSpan.FromDays(1));
await cacheLayer.SetAsync("AssertGetSetCache", cacheEntry);
var cacheEntryGet = await cacheLayer.GetAsync("AssertGetSetCache");
@@ -39,7 +39,7 @@ protected static async Task AssertCacheAvailabilityAsync(IAsyncCacheLayer cacheL
protected static void AssertCacheEviction(ISyncCacheLayer cacheLayer)
{
- var cacheEntry = new CacheEntry(77, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(77, TimeSpan.FromDays(1));
cacheLayer.Set("AssertCacheEviction-ToEvict", cacheEntry);
cacheLayer.Set("AssertCacheEviction-ToKeep", cacheEntry);
@@ -57,7 +57,7 @@ protected static void AssertCacheEviction(ISyncCacheLayer cacheLayer)
}
protected static async Task AssertCacheEvictionAsync(IAsyncCacheLayer cacheLayer)
{
- var cacheEntry = new CacheEntry(77, DateTime.UtcNow, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(77, TimeSpan.FromDays(1));
await cacheLayer.SetAsync("AssertCacheEviction-ToEvict", cacheEntry);
await cacheLayer.SetAsync("AssertCacheEviction-ToKeep", cacheEntry);
@@ -80,7 +80,7 @@ CacheEntry DoCleanupTest(DateTime dateTime)
{
var cacheKey = $"AssertCacheCleanup-(DateTime:{dateTime})";
- var cacheEntry = new CacheEntry(98, dateTime, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(98, dateTime);
cacheLayer.Set(cacheKey, cacheEntry);
cacheLayer.Cleanup();
@@ -88,8 +88,8 @@ CacheEntry DoCleanupTest(DateTime dateTime)
return cacheLayer.Get(cacheKey);
}
- Assert.IsNotNull(DoCleanupTest(DateTime.UtcNow), "Cleanup removed entry that was still live");
- Assert.IsNull(DoCleanupTest(DateTime.UtcNow.AddDays(-2)), "Cleanup kept entry past the end of life");
+ Assert.IsNotNull(DoCleanupTest(DateTime.UtcNow.AddDays(1)), "Cleanup removed entry that was still live");
+ Assert.IsNull(DoCleanupTest(DateTime.UtcNow.AddDays(-1)), "Cleanup kept entry past the end of life");
}
protected static async Task AssertCacheCleanupAsync(IAsyncCacheLayer cacheLayer)
{
@@ -97,7 +97,7 @@ async Task> DoCleanupTest(DateTime dateTime)
{
var cacheKey = $"AssertCacheCleanup-(DateTime:{dateTime})";
- var cacheEntry = new CacheEntry(98, dateTime, TimeSpan.FromDays(1));
+ var cacheEntry = new CacheEntry(98, dateTime);
await cacheLayer.SetAsync(cacheKey, cacheEntry);
await cacheLayer.CleanupAsync();
@@ -105,8 +105,8 @@ async Task> DoCleanupTest(DateTime dateTime)
return await cacheLayer.GetAsync(cacheKey);
}
- Assert.IsNotNull(await DoCleanupTest(DateTime.UtcNow), "Cleanup removed entry that was still live");
- Assert.IsNull(await DoCleanupTest(DateTime.UtcNow.AddDays(-2)), "Cleanup kept entry past the end of life");
+ Assert.IsNotNull(await DoCleanupTest(DateTime.UtcNow.AddDays(1)), "Cleanup removed entry that was still live");
+ Assert.IsNull(await DoCleanupTest(DateTime.UtcNow.AddDays(-1)), "Cleanup kept entry past the end of life");
}
protected static void AssertComplexTypeCaching(ISyncCacheLayer cacheLayer)
@@ -116,7 +116,7 @@ protected static void AssertComplexTypeCaching(ISyncCacheLayer cacheLayer)
ExampleString = "Hello World",
ExampleNumber = 99,
ListOfNumbers = new List() { 1, 2, 4, 8 }
- }, DateTime.UtcNow, TimeSpan.FromDays(1));
+ }, TimeSpan.FromDays(1));
cacheLayer.Set("ComplexTypeOne", complexTypeOneEntry);
var complexTypeOneEntryGet = cacheLayer.Get("ComplexTypeOne");
@@ -127,7 +127,7 @@ protected static void AssertComplexTypeCaching(ISyncCacheLayer cacheLayer)
ExampleString = "Hello World",
ArrayOfObjects = new[] { complexTypeOneEntry.Value },
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "Z", 26 } }
- }, DateTime.UtcNow, TimeSpan.FromDays(1));
+ }, TimeSpan.FromDays(1));
cacheLayer.Set("ComplexTypeTwo", complexTypeTwoEntry);
var complexTypeTwoEntryGet = cacheLayer.Get("ComplexTypeTwo");
@@ -140,7 +140,7 @@ protected static async Task AssertComplexTypeCachingAsync(IAsyncCacheLayer cache
ExampleString = "Hello World",
ExampleNumber = 99,
ListOfNumbers = new List() { 1, 2, 4, 8 }
- }, DateTime.UtcNow, TimeSpan.FromDays(1));
+ }, TimeSpan.FromDays(1));
await cacheLayer.SetAsync("ComplexTypeOne", complexTypeOneEntry);
var complexTypeOneEntryGet = await cacheLayer.GetAsync("ComplexTypeOne");
@@ -151,7 +151,7 @@ protected static async Task AssertComplexTypeCachingAsync(IAsyncCacheLayer cache
ExampleString = "Hello World",
ArrayOfObjects = new[] { complexTypeOneEntry.Value },
DictionaryOfNumbers = new Dictionary() { { "A", 1 }, { "Z", 26 } }
- }, DateTime.UtcNow, TimeSpan.FromDays(1));
+ }, TimeSpan.FromDays(1));
await cacheLayer.SetAsync("ComplexTypeTwo", complexTypeTwoEntry);
var complexTypeTwoEntryGet = await cacheLayer.GetAsync("ComplexTypeTwo");
diff --git a/tests/CacheTower.Tests/Providers/Database/MongoDB/MongoDbCacheLayerTests.cs b/tests/CacheTower.Tests/Providers/Database/MongoDB/MongoDbCacheLayerTests.cs
index 3b40f2c4..1af58a7e 100644
--- a/tests/CacheTower.Tests/Providers/Database/MongoDB/MongoDbCacheLayerTests.cs
+++ b/tests/CacheTower.Tests/Providers/Database/MongoDB/MongoDbCacheLayerTests.cs
@@ -8,6 +8,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoDB.Driver;
using MongoFramework;
+using Moq;
namespace CacheTower.Tests.Providers.Database.MongoDB
{
@@ -36,6 +37,11 @@ public async Task GetSetCache()
public async Task IsCacheAvailable()
{
await AssertCacheAvailabilityAsync(new MongoDbCacheLayer(MongoDbHelper.GetConnection()), true);
+
+ var connectionMock = new Mock();
+ connectionMock.Setup(c => c.GetDatabase()).Throws();
+
+ await AssertCacheAvailabilityAsync(new MongoDbCacheLayer(connectionMock.Object), false);
}
[TestMethod]
diff --git a/tests/CacheTower.Tests/Providers/FileSystem/FileCacheLayerBaseTests.cs b/tests/CacheTower.Tests/Providers/FileSystem/FileCacheLayerBaseTests.cs
index 0881359f..7568f27a 100644
--- a/tests/CacheTower.Tests/Providers/FileSystem/FileCacheLayerBaseTests.cs
+++ b/tests/CacheTower.Tests/Providers/FileSystem/FileCacheLayerBaseTests.cs
@@ -77,7 +77,7 @@ private string GetMD5String(string text)
public async Task NoFileExtension()
{
var cacheLayer = new TestFileCacheLayer(DirectoryPath, null);
- await cacheLayer.SetAsync("NoFileExtension", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await cacheLayer.SetAsync("NoFileExtension", new CacheEntry(1, TimeSpan.FromDays(1)));
await DisposeOf(cacheLayer);
var md5String = GetMD5String("NoFileExtension");
@@ -88,7 +88,7 @@ public async Task NoFileExtension()
public async Task CustomFileExtension()
{
var cacheLayer = new TestFileCacheLayer(DirectoryPath, ".mycustomfileextension");
- await cacheLayer.SetAsync("CustomFileExtension", new CacheEntry(1, DateTime.UtcNow, TimeSpan.FromDays(1)));
+ await cacheLayer.SetAsync("CustomFileExtension", new CacheEntry(1, TimeSpan.FromDays(1)));
await DisposeOf(cacheLayer);
var md5String = GetMD5String("CustomFileExtension");
diff --git a/tests/CacheTower.Tests/Providers/Redis/RedisCacheLayerTests.cs b/tests/CacheTower.Tests/Providers/Redis/RedisCacheLayerTests.cs
index 07b7181c..d8371692 100644
--- a/tests/CacheTower.Tests/Providers/Redis/RedisCacheLayerTests.cs
+++ b/tests/CacheTower.Tests/Providers/Redis/RedisCacheLayerTests.cs
@@ -6,6 +6,7 @@
using CacheTower.Providers.Redis;
using CacheTower.Tests.Utils;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
using StackExchange.Redis;
namespace CacheTower.Tests.Providers.Redis
@@ -29,6 +30,13 @@ public async Task GetSetCache()
public async Task IsCacheAvailable()
{
await AssertCacheAvailabilityAsync(new RedisCacheLayer(RedisHelper.GetConnection()), true);
+
+ var connectionMock = new Mock();
+ var databaseMock = new Mock();
+ connectionMock.Setup(cm => cm.GetDatabase(It.IsAny(), It.IsAny