From 693b94653c2a3603620141084c1219d0cf1d7ed1 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 12:07:18 +0000 Subject: [PATCH 01/10] Update copyright year --- src/GlobalAssemblyInfo.cs | 2 +- src/Polly.Caching.Memory.nuspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs index 93e9b6a..557d354 100644 --- a/src/GlobalAssemblyInfo.cs +++ b/src/GlobalAssemblyInfo.cs @@ -3,7 +3,7 @@ [assembly: AssemblyProduct("Polly.Caching.Memory")] [assembly: AssemblyCompany("App vNext")] [assembly: AssemblyDescription("Polly.Caching.Memory is a MemoryCache plug-in for the Polly CachePolicy. Polly is a library that allows developers to express resilience and transient fault handling policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.")] -[assembly: AssemblyCopyright("Copyright (c) 2018, App vNext")] +[assembly: AssemblyCopyright("Copyright (c) 2019, App vNext")] #if DEBUG [assembly: AssemblyConfiguration("Debug")] diff --git a/src/Polly.Caching.Memory.nuspec b/src/Polly.Caching.Memory.nuspec index 105819a..ffbbc4b 100644 --- a/src/Polly.Caching.Memory.nuspec +++ b/src/Polly.Caching.Memory.nuspec @@ -11,7 +11,7 @@ https://raw.github.com/App-vNext/Polly/master/Polly.png https://github.com/App-vNext/Polly.Caching.MemoryCache Polly Cache Caching Cache-aside - Copyright © 2018, App vNext + Copyright © 2019, App vNext 2.0.1 --------------------- From 7a9f6491c32bec4caae0ac8ef4e90da46aeeb2cf Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 12:09:08 +0000 Subject: [PATCH 02/10] Update license element in nuspec Fixes #31 --- src/Polly.Caching.Memory.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Polly.Caching.Memory.nuspec b/src/Polly.Caching.Memory.nuspec index ffbbc4b..1b6eb08 100644 --- a/src/Polly.Caching.Memory.nuspec +++ b/src/Polly.Caching.Memory.nuspec @@ -7,7 +7,7 @@ Polly.Caching.Memory is a plug-in for the .NET OSS resilience library Polly, supporting System.Runtime.Caching.MemoryCache as a provider for Polly's CachePolicy. en-US - https://raw.github.com/App-vNext/Polly/master/LICENSE.txt + BSD-3-Clause https://raw.github.com/App-vNext/Polly/master/Polly.png https://github.com/App-vNext/Polly.Caching.MemoryCache Polly Cache Caching Cache-aside From 86af6ff0d02e55a382e32a6474546882d75899d1 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 12:25:27 +0000 Subject: [PATCH 03/10] Add v2.0.2 doco --- CHANGELOG.md | 4 ++++ GitVersionConfig.yaml | 2 +- README.md | 17 ++++++++++++++--- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- src/Polly.Caching.Memory.nuspec | 9 +++++++-- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da0af7..37591e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Polly.Caching.MemoryCache change log +## 2.0.2 +- No functional changes +- Indicate compatibility with Polly < v7 + ## 2.0.1 - Upgrade for compatibility with Polly v6.1.1 diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml index 58c9946..02d54e2 100644 --- a/GitVersionConfig.yaml +++ b/GitVersionConfig.yaml @@ -1 +1 @@ -next-version: 2.0.1 \ No newline at end of file +next-version: 2.0.2 \ No newline at end of file diff --git a/README.md b/README.md index f797a97..5559bb4 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,22 @@ Polly.Caching.Memory >= v2.0 supports .NET Standard 1.3 and .NET Standard 2.0 Polly.Caching.MemoryCache <v2.0 supports .NET4.0, .NET4.5 and .NetStandard 1.3 -## Dependencies +## Versions and Dependencies -Polly.Caching.Memory >= v2.0 works with Polly v6.0.1 and above. +Polly.Caching.Memory >=v2.0.2 and <v3 requires: -Polly.Caching.MemoryCache <v2.0 works with Polly v5.9.0 and above. ++ [Polly](https://nuget.org/packages/polly) >= v6.1.1 and <v7. ++ [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v2.0.2 or above (or v1.1.2, for NetStandard 1.3). + +Polly.Caching.Memory >= v2.0.1 requires: + ++ [Polly](https://nuget.org/packages/polly) >= v6.0.1 and <=v6.1.0. ++ [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v2.0.2 or above (or v1.1.2, for NetStandard 1.3). + +Polly.Caching.MemoryCache <v1.* requires: + ++ [Polly](https://nuget.org/packages/polly) >=v5.9.0 and <v6. ++ [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v1.1.2, for NetStandard 1.3. # How to use the Polly.Caching.Memory plugin diff --git a/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs b/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs index a165d38..771f2b5 100644 --- a/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs +++ b/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs @@ -4,8 +4,8 @@ [assembly: AssemblyTitle("Polly.Caching.Memory")] [assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.1.0")] -[assembly: AssemblyInformationalVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.2.0")] +[assembly: AssemblyInformationalVersion("2.0.2.0")] [assembly: CLSCompliant(false)] // Because Microsoft.Extensions.Caching.Memory.MemoryCache, on which Polly.Caching.MemoryCache.NetStandard13 depends, is not CLSCompliant. [assembly: InternalsVisibleTo("Polly.Caching.Memory.NetStandard13.Specs")] \ No newline at end of file diff --git a/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs b/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs index 96ec3d1..a8bea94 100644 --- a/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs +++ b/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs @@ -4,8 +4,8 @@ [assembly: AssemblyTitle("Polly.Caching.Memory")] [assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.1.0")] -[assembly: AssemblyInformationalVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.2.0")] +[assembly: AssemblyInformationalVersion("2.0.2.0")] [assembly: CLSCompliant(false)] // Because Microsoft.Extensions.Caching.Memory.MemoryCache, on which Polly.Caching.MemoryCache.NetStandard13 depends, is not CLSCompliant. [assembly: InternalsVisibleTo("Polly.Caching.Memory.NetStandard20.Specs")] \ No newline at end of file diff --git a/src/Polly.Caching.Memory.nuspec b/src/Polly.Caching.Memory.nuspec index 1b6eb08..8f3268c 100644 --- a/src/Polly.Caching.Memory.nuspec +++ b/src/Polly.Caching.Memory.nuspec @@ -13,6 +13,11 @@ Polly Cache Caching Cache-aside Copyright © 2019, App vNext + 2.0.2 + --------------------- + - No functional changes + - Indicate compatibility with Polly < v7 + 2.0.1 --------------------- - Upgrade for compatibility with Polly v6.1.1 @@ -48,11 +53,11 @@ - + - + From 5058c749fe944b3c14e75819fde8cf5779e4dbfb Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 12:29:23 +0000 Subject: [PATCH 04/10] Move existing specs to unit test folder --- .../Polly.Caching.Memory.SharedSpecs.projitems | 2 +- .../{ => Unit}/MemoryCacheProviderSpecs.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/Polly.Caching.Memory.SharedSpecs/{ => Unit}/MemoryCacheProviderSpecs.cs (99%) diff --git a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems index e3271db..0d39c43 100644 --- a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems +++ b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems @@ -9,6 +9,6 @@ Polly.Caching.Memory.Specs - + \ No newline at end of file diff --git a/src/Polly.Caching.Memory.SharedSpecs/MemoryCacheProviderSpecs.cs b/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs similarity index 99% rename from src/Polly.Caching.Memory.SharedSpecs/MemoryCacheProviderSpecs.cs rename to src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs index 2b6c2fd..4240eee 100644 --- a/src/Polly.Caching.Memory.SharedSpecs/MemoryCacheProviderSpecs.cs +++ b/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs @@ -6,7 +6,7 @@ using Polly.Caching.Memory; using Microsoft.Extensions.Caching.Memory; -namespace Polly.Specs.Caching.Memory +namespace Polly.Specs.Caching.Memory.Unit { public class MemoryCacheProviderSpecs { From 307150989e28b9c6658662dc3308f466bcf1c08c Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 13:21:34 +0000 Subject: [PATCH 05/10] Add test expectations for v3.0.0 --- ....Caching.Memory.NetStandard13.Specs.csproj | 1 + .../Integration/CacheProviderExtensions.cs | 21 +++ .../Integration/CacheRoundTripSpecsBase.cs | 131 ++++++++++++++++++ .../CacheRoundTripSpecsSyncBase.cs | 52 +++++++ ...cs_NetStandardMemoryCacheProvider_Async.cs | 8 ++ ...ecs_NetStandardMemoryCacheProvider_Sync.cs | 8 ++ .../CacheRoundTripspecsAsyncBase.cs | 51 +++++++ .../Integration/ICachePolicyFactory.cs | 8 ++ .../Integration/MemoryCachePolicyFactory.cs | 26 ++++ ...Polly.Caching.Memory.SharedSpecs.projitems | 8 ++ 10 files changed, 314 insertions(+) create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsBase.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsSyncBase.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripspecsAsyncBase.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/ICachePolicyFactory.cs create mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/MemoryCachePolicyFactory.cs diff --git a/src/Polly.Caching.Memory.NetStandard13.Specs/Polly.Caching.Memory.NetStandard13.Specs.csproj b/src/Polly.Caching.Memory.NetStandard13.Specs/Polly.Caching.Memory.NetStandard13.Specs.csproj index fd59df7..8724a29 100644 --- a/src/Polly.Caching.Memory.NetStandard13.Specs/Polly.Caching.Memory.NetStandard13.Specs.csproj +++ b/src/Polly.Caching.Memory.NetStandard13.Specs/Polly.Caching.Memory.NetStandard13.Specs.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs new file mode 100644 index 0000000..6112df6 --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs @@ -0,0 +1,21 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Polly.Caching.Memory.Specs.Integration +{ + public static class CacheProviderExtensions + { + public static (bool, TResult) TryGet(this ISyncCacheProvider provider, string key) + { + var fromCache = provider.Get(key); + return (fromCache != null, fromCache); + } + + public static async Task<(bool, TResult)> TryGetAsync(this IAsyncCacheProvider provider, string key, CancellationToken token, bool continueOnCapturedContext) + { + var fromCache = await provider.GetAsync(key, token, continueOnCapturedContext); + return (fromCache != null, fromCache); + } + + } +} diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsBase.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsBase.cs new file mode 100644 index 0000000..2914c1c --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsBase.cs @@ -0,0 +1,131 @@ +using System; +using System.Threading.Tasks; +using Xunit; + +namespace Polly.Caching.Memory.Specs.Integration +{ + public abstract class CacheRoundTripSpecsBase + { + protected CacheRoundTripSpecsBase(ICachePolicyFactory cachePolicyFactory) + { + CachePolicyFactory = cachePolicyFactory; + } + + protected ICachePolicyFactory CachePolicyFactory { get; } + + protected const string OperationKey = "SomeOperationKey"; + + public abstract Task Should_roundtrip_this_variant_of(TResult testValue); + + [Theory] + [MemberData(nameof(SampleClassData))] + public async Task Should_roundtrip_all_variants_of_reference_type(SampleClass testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + [Theory] + [MemberData(nameof(SampleStringData))] + public async Task Should_roundtrip_all_variants_of_string(String testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + [Theory] + [MemberData(nameof(SampleNumericData))] + public async Task Should_roundtrip_all_variants_of_numeric(int testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + [Theory] + [MemberData(nameof(SampleEnumData))] + public async Task Should_roundtrip_all_variants_of_enum(SampleEnum testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + [Theory] + [MemberData(nameof(SampleBoolData))] + public async Task Should_roundtrip_all_variants_of_bool(bool testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + [Theory] + [MemberData(nameof(SampleNullableBoolData))] + public async Task Should_roundtrip_all_variants_of_nullable_bool(bool? testValue) + { + await Should_roundtrip_this_variant_of(testValue); + } + + public static TheoryData SampleClassData => + new TheoryData + { + new SampleClass(), + new SampleClass() + { + StringProperty = "", + IntProperty = 1 + }, + (SampleClass)null, + default(SampleClass) + }; + + public static TheoryData SampleStringData => + new TheoryData + { + "some string", + "", + null, + default(string), + "null" + }; + + public static TheoryData SampleNumericData => + new TheoryData + { + -1, + 0, + 1, + default(int) + }; + + public static TheoryData SampleEnumData => + new TheoryData + { + SampleEnum.FirstValue, + SampleEnum.SecondValue, + default(SampleEnum), + }; + + public static TheoryData SampleBoolData => + new TheoryData + { + true, + false, + default(bool), + }; + + public static TheoryData SampleNullableBoolData => + new TheoryData + { + true, + false, + null, + default(bool?), + }; + + public class SampleClass + { + public string StringProperty { get; set; } + public int IntProperty { get; set; } + } + + public enum SampleEnum + { + FirstValue, + SecondValue, + } + } +} diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsSyncBase.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsSyncBase.cs new file mode 100644 index 0000000..5a13364 --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecsSyncBase.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading.Tasks; +using FluentAssertions; + +namespace Polly.Caching.Memory.Specs.Integration +{ + public abstract class CacheRoundTripSpecsSyncBase : CacheRoundTripSpecsBase + { + protected CacheRoundTripSpecsSyncBase(ICachePolicyFactory cachePolicyFactory) : base(cachePolicyFactory) + { + } + + public override Task Should_roundtrip_this_variant_of(TResult testValue) + { + // Arrange + var (cacheProvider, cache) = CachePolicyFactory.CreateSyncCachePolicy(); + + // Assert - should not be in cache + (bool cacheHit1, TResult fromCache1) = cacheProvider.TryGet(OperationKey); + cacheHit1.Should().BeFalse(); + fromCache1.Should().Be(default(TResult)); + + // Act - should execute underlying delegate and place in cache + int underlyingDelegateExecuteCount = 0; + cache.Execute(ctx => + { + underlyingDelegateExecuteCount++; + return testValue; + }, new Context(OperationKey)) + .ShouldBeEquivalentTo(testValue); + + // Assert - should have executed underlying delegate + underlyingDelegateExecuteCount.Should().Be(1); + + // Assert - should be in cache + (bool cacheHit2, TResult fromCache2) = cacheProvider.TryGet(OperationKey); + cacheHit2.Should().BeTrue(); + fromCache2.ShouldBeEquivalentTo(testValue); + + // Act - should execute underlying delegate and place in cache + cache.Execute(ctx => + { + underlyingDelegateExecuteCount++; + throw new Exception("Cache should be used so this should not get invoked."); + }, new Context(OperationKey)) + .ShouldBeEquivalentTo(testValue); + underlyingDelegateExecuteCount.Should().Be(1); + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async.cs new file mode 100644 index 0000000..34cf1db --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async.cs @@ -0,0 +1,8 @@ +namespace Polly.Caching.Memory.Specs.Integration +{ + public class CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async : CacheRoundTripSpecsAsyncBase { + public CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Async() : base(new MemoryCachePolicyFactory()) + { + } + } +} \ No newline at end of file diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync.cs new file mode 100644 index 0000000..4b83ec0 --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync.cs @@ -0,0 +1,8 @@ +namespace Polly.Caching.Memory.Specs.Integration +{ + public class CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync : CacheRoundTripSpecsSyncBase { + public CacheRoundTripSpecs_NetStandardMemoryCacheProvider_Sync() : base(new MemoryCachePolicyFactory()) + { + } + } +} \ No newline at end of file diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripspecsAsyncBase.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripspecsAsyncBase.cs new file mode 100644 index 0000000..3bbd2e6 --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheRoundTripspecsAsyncBase.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions; + +namespace Polly.Caching.Memory.Specs.Integration +{ + public abstract class CacheRoundTripSpecsAsyncBase : CacheRoundTripSpecsBase + { + protected CacheRoundTripSpecsAsyncBase(ICachePolicyFactory cachePolicyFactory) : base(cachePolicyFactory) + { + } + + public override async Task Should_roundtrip_this_variant_of(TResult testValue) + { + // Arrange + var (cacheProvider, cache) = CachePolicyFactory.CreateAsyncCachePolicy(); + + // Assert - should not be in cache + (bool cacheHit1, TResult fromCache1) = await cacheProvider.TryGetAsync(OperationKey, CancellationToken.None, false); + cacheHit1.Should().BeFalse(); + fromCache1.Should().Be(default(TResult)); + + // Act - should execute underlying delegate and place in cache + int underlyingDelegateExecuteCount = 0; + (await cache.ExecuteAsync(ctx => + { + underlyingDelegateExecuteCount++; + return Task.FromResult(testValue); + }, new Context(OperationKey))) + .ShouldBeEquivalentTo(testValue); + + // Assert - should have executed underlying delegate + underlyingDelegateExecuteCount.Should().Be(1); + + // Assert - should be in cache + (bool cacheHit2, TResult fromCache2) = await cacheProvider.TryGetAsync(OperationKey, CancellationToken.None, false); + cacheHit2.Should().BeTrue(); + fromCache2.ShouldBeEquivalentTo(testValue); + + // Act - should execute underlying delegate and place in cache + (await cache.ExecuteAsync(ctx => + { + underlyingDelegateExecuteCount++; + throw new Exception("Cache should be used so this should not get invoked."); + }, new Context(OperationKey))) + .ShouldBeEquivalentTo(testValue); + underlyingDelegateExecuteCount.Should().Be(1); + } + } +} \ No newline at end of file diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/ICachePolicyFactory.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/ICachePolicyFactory.cs new file mode 100644 index 0000000..1020f3a --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/ICachePolicyFactory.cs @@ -0,0 +1,8 @@ +namespace Polly.Caching.Memory.Specs.Integration +{ + public interface ICachePolicyFactory + { + (ISyncCacheProvider, ISyncPolicy) CreateSyncCachePolicy(); + (IAsyncCacheProvider, IAsyncPolicy) CreateAsyncCachePolicy(); + } +} diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/MemoryCachePolicyFactory.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/MemoryCachePolicyFactory.cs new file mode 100644 index 0000000..4bae172 --- /dev/null +++ b/src/Polly.Caching.Memory.SharedSpecs/Integration/MemoryCachePolicyFactory.cs @@ -0,0 +1,26 @@ +using System; +using Microsoft.Extensions.Caching.Memory; + +namespace Polly.Caching.Memory.Specs.Integration +{ + public class MemoryCachePolicyFactory : ICachePolicyFactory + { + public (ISyncCacheProvider, ISyncPolicy) CreateSyncCachePolicy() + { + IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); + ISyncCacheProvider provider = new MemoryCacheProvider(memoryCache).For(); + + var policy = Policy.Cache(provider, TimeSpan.FromHours(1)); + return (provider, policy); + } + + public (IAsyncCacheProvider, IAsyncPolicy) CreateAsyncCachePolicy() + { + IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); + IAsyncCacheProvider provider = new MemoryCacheProvider(memoryCache).AsyncFor(); + + var policy = Policy.CacheAsync(provider, TimeSpan.FromHours(1)); + return (provider, policy); + } + } +} diff --git a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems index 0d39c43..9ac792d 100644 --- a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems +++ b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems @@ -9,6 +9,14 @@ Polly.Caching.Memory.Specs + + + + + + + + \ No newline at end of file From 580819044c4ec94af47e4fb1bbe21ae55e31002d Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 13:41:57 +0000 Subject: [PATCH 06/10] Migrate memory cache provider implementations to Polly v7.0.0 --- .../Polly.Caching.Memory.NetStandard13.csproj | 3 +- .../Polly.Caching.Memory.NetStandard20.csproj | 2 +- .../MemoryCacheProvider.cs | 40 +++++++++---------- .../Integration/CacheProviderExtensions.cs | 21 ---------- ...Polly.Caching.Memory.SharedSpecs.projitems | 1 - .../Unit/MemoryCacheProviderSpecs.cs | 18 ++++----- 6 files changed, 31 insertions(+), 54 deletions(-) delete mode 100644 src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs diff --git a/src/Polly.Caching.Memory.NetStandard13/Polly.Caching.Memory.NetStandard13.csproj b/src/Polly.Caching.Memory.NetStandard13/Polly.Caching.Memory.NetStandard13.csproj index be7b76c..a2f1b20 100644 --- a/src/Polly.Caching.Memory.NetStandard13/Polly.Caching.Memory.NetStandard13.csproj +++ b/src/Polly.Caching.Memory.NetStandard13/Polly.Caching.Memory.NetStandard13.csproj @@ -29,7 +29,8 @@ - + + \ No newline at end of file diff --git a/src/Polly.Caching.Memory.NetStandard20/Polly.Caching.Memory.NetStandard20.csproj b/src/Polly.Caching.Memory.NetStandard20/Polly.Caching.Memory.NetStandard20.csproj index a1b21a0..97e7b4d 100644 --- a/src/Polly.Caching.Memory.NetStandard20/Polly.Caching.Memory.NetStandard20.csproj +++ b/src/Polly.Caching.Memory.NetStandard20/Polly.Caching.Memory.NetStandard20.csproj @@ -29,7 +29,7 @@ - + \ No newline at end of file diff --git a/src/Polly.Caching.Memory.Shared/MemoryCacheProvider.cs b/src/Polly.Caching.Memory.Shared/MemoryCacheProvider.cs index 5f4d400..0ced952 100644 --- a/src/Polly.Caching.Memory.Shared/MemoryCacheProvider.cs +++ b/src/Polly.Caching.Memory.Shared/MemoryCacheProvider.cs @@ -19,25 +19,23 @@ public class MemoryCacheProvider : ISyncCacheProvider, IAsyncCacheProvider /// The memory cache instance in which to store cached items. public MemoryCacheProvider(IMemoryCache memoryCache) { - if (memoryCache == null) throw new ArgumentNullException(nameof(memoryCache)); - _cache = memoryCache; + _cache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); } /// /// Gets a value from cache. /// /// The cache key. - /// The value from cache; or null, if none was found. - public object Get(String key) + /// + /// A tuple whose first element is a value indicating whether the key was found in the cache, + /// and whose second element is the value from the cache (null if not found). + /// + public (bool, object) TryGet(string key) { - object value; - if (_cache.TryGetValue(key, out value)) - { - return value; - } - return null; + bool cacheHit = _cache.TryGetValue(key, out var value); + return (cacheHit, value); } - + /// /// Puts the specified value in the cache. /// @@ -59,7 +57,7 @@ public void Put(string key, object value, Ttl ttl) { options.AbsoluteExpiration = DateTimeOffset.MaxValue; } -else + else { options.AbsoluteExpirationRelativeToNow = ttl.Timespan < remaining ? ttl.Timespan : remaining; } @@ -69,17 +67,20 @@ public void Put(string key, object value, Ttl ttl) } /// - /// Gets a value from the memory cache as part of an asynchronous execution. The implementation is synchronous as there is no advantage to an asynchronous implementation for an in-memory cache. + /// Gets a value from the cache asynchronously. + /// The implementation is synchronous as there is no advantage to an asynchronous implementation for an in-memory cache. /// /// The cache key. - /// The cancellation token. - /// Whether async calls should continue on a captured synchronization context. For , this parameter is irrelevant and is ignored, as the implementation is synchronous. - /// A promising as Result the value from cache; or null, if none was found. - public Task GetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext) + /// The cancellation token. + /// Whether async calls should continue on a captured synchronization context. Note: if the underlying cache's async API does not support controlling whether to continue on a captured context, async Policy executions with continueOnCapturedContext == true cannot be guaranteed to remain on the captured context. + /// + /// A promising as Result a tuple whose first element is a value indicating whether + /// the key was found in the cache, and whose second element is the value from the cache (null if not found). + /// + public Task<(bool, object)> TryGetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext) { cancellationToken.ThrowIfCancellationRequested(); - return Task.FromResult(Get(key)); - // (With C#7.0, a ValueTask<> approach would be preferred, but some of our tfms do not support that. TO DO: Implement it, with preprocessor if/endif directives, for NetStandard) + return Task.FromResult(TryGet(key)); } /// @@ -97,7 +98,6 @@ public Task PutAsync(string key, object value, Ttl ttl, CancellationToken cancel cancellationToken.ThrowIfCancellationRequested(); Put(key, value, ttl); return Task.CompletedTask; - // (With C#7.0, a ValueTask<> approach would be preferred, but some of our tfms do not support that. TO DO: Implement it, with preprocessor if/endif directives, for NetStandard) } } } diff --git a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs b/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs deleted file mode 100644 index 6112df6..0000000 --- a/src/Polly.Caching.Memory.SharedSpecs/Integration/CacheProviderExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace Polly.Caching.Memory.Specs.Integration -{ - public static class CacheProviderExtensions - { - public static (bool, TResult) TryGet(this ISyncCacheProvider provider, string key) - { - var fromCache = provider.Get(key); - return (fromCache != null, fromCache); - } - - public static async Task<(bool, TResult)> TryGetAsync(this IAsyncCacheProvider provider, string key, CancellationToken token, bool continueOnCapturedContext) - { - var fromCache = await provider.GetAsync(key, token, continueOnCapturedContext); - return (fromCache != null, fromCache); - } - - } -} diff --git a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems index 9ac792d..5f69bab 100644 --- a/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems +++ b/src/Polly.Caching.Memory.SharedSpecs/Polly.Caching.Memory.SharedSpecs.projitems @@ -9,7 +9,6 @@ Polly.Caching.Memory.Specs - diff --git a/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs b/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs index 4240eee..f8d0c17 100644 --- a/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs +++ b/src/Polly.Caching.Memory.SharedSpecs/Unit/MemoryCacheProviderSpecs.cs @@ -42,28 +42,26 @@ public void Get_should_return_instance_previously_stored_in_cache() string key = Guid.NewGuid().ToString(); object value = new object(); -#if PORTABLE - using (Microsoft.Extensions.Caching.Memory.ICacheEntry entry = memoryCache.CreateEntry(key)) { + using (ICacheEntry entry = memoryCache.CreateEntry(key)) { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10); entry.Value = value; } -#else - memoryCache[key] = value; -#endif MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); - object got = provider.Get(key); - got.Should().BeSameAs(value); + (bool cacheHit, object payload) = provider.TryGet(key); + cacheHit.Should().BeTrue(); + payload.Should().BeSameAs(value); } [Fact] - public void Get_should_return_null_on_unknown_key() + public void Get_should_return_false_on_unknown_key() { IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); - object got = provider.Get(Guid.NewGuid().ToString()); - got.Should().BeNull(); + (bool cacheHit, object payload) = provider.TryGet(Guid.NewGuid().ToString()); + cacheHit.Should().BeFalse(); + payload.Should().BeNull(); } #endregion From e2ccd61a58ffaacfacf2adb68f51321a781a8dce Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 14:01:04 +0000 Subject: [PATCH 07/10] Corrections to previous version requirements --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5559bb4..9c4d70f 100644 --- a/README.md +++ b/README.md @@ -27,17 +27,17 @@ Polly.Caching.MemoryCache <v2.0 supports .NET4.0, .NET4.5 and .NetStandard 1. ## Versions and Dependencies -Polly.Caching.Memory >=v2.0.2 and <v3 requires: +Polly.Caching.Memory >=v2.0.1 and <v3 requires: + [Polly](https://nuget.org/packages/polly) >= v6.1.1 and <v7. + [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v2.0.2 or above (or v1.1.2, for NetStandard 1.3). -Polly.Caching.Memory >= v2.0.1 requires: +Polly.Caching.Memory v2.0.0 requires: + [Polly](https://nuget.org/packages/polly) >= v6.0.1 and <=v6.1.0. + [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v2.0.2 or above (or v1.1.2, for NetStandard 1.3). -Polly.Caching.MemoryCache <v1.* requires: +Polly.Caching.MemoryCache v1.* requires: + [Polly](https://nuget.org/packages/polly) >=v5.9.0 and <v6. + [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v1.1.2, for NetStandard 1.3. From f58c67362e6f2950db38c869973688286e261c2a Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 14:03:28 +0000 Subject: [PATCH 08/10] General readme improvements --- README.md | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9c4d70f..0c772b6 100644 --- a/README.md +++ b/README.md @@ -44,32 +44,25 @@ Polly.Caching.MemoryCache v1.* requires: # How to use the Polly.Caching.Memory plugin -```csharp -// (1a): Create a MemoryCacheProvider instance in the .NET Framework, using the Polly.Caching.Memory nuget package. -// (full namespaces and types only shown here for disambiguation) -Polly.Caching.Memory.MemoryCacheProvider memoryCacheProvider - = new Polly.Caching.Memory.MemoryCacheProvider(System.Runtime.Caching.MemoryCache.Default); +### Example: Direct creation of CachePolicy (no DI) -// Or (1b): Create a MemoryCacheProvider instance in .NET Core / .NET Standard. -// (full namespaces and types only shown here for disambiguation) -// NB Only if you want to create your own Microsoft.Extensions.Caching.Memory.MemoryCache instance: +```csharp +// This approach creates a CachePolicy directly, with its own Microsoft.Extensions.Caching.Memory.MemoryCache instance: Microsoft.Extensions.Caching.Memory.IMemoryCache memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); Polly.Caching.Memory.MemoryCacheProvider memoryCacheProvider = new Polly.Caching.Memory.MemoryCacheProvider(memoryCache); -// (2) Create a Polly cache policy using that Polly.Caching.Memory.MemoryCacheProvider instance. +// Create a Polly cache policy using that Polly.Caching.Memory.MemoryCacheProvider instance. var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5)); +``` +### Example: Configure CachePolicy via MemoryCacheProvider in StartUp, for DI +```csharp +// (We pass a whole PolicyRegistry by dependency injection rather than the individual policy, +// on the assumption the app will probably use multiple policies.) -// Or (1c): Configure by dependency injection within ASP.NET Core -// See https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory -// and https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#registering-your-own-services - -// (In this example we choose to pass a whole PolicyRegistry by dependency injection rather than the individual policy, on the assumption the webapp will probably use multiple policies across the app.) - -// For example: public class Startup { public void ConfigureServices(IServiceCollection services) @@ -77,10 +70,15 @@ public class Startup services.AddMemoryCache(); services.AddSingleton(); - services.AddSingleton, Polly.Registry.PolicyRegistry>((serviceProvider) => + services.AddSingleton, Polly.Registry.PolicyRegistry>((serviceProvider) => { PolicyRegistry registry = new PolicyRegistry(); - registry.Add("myCachePolicy", Policy.CacheAsync(serviceProvider.GetRequiredService().AsyncFor(), TimeSpan.FromMinutes(5))); + registry.Add("myCachePolicy", + Policy.CacheAsync( + serviceProvider + .GetRequiredService() + .AsyncFor(), + TimeSpan.FromMinutes(5))); return registry; }); @@ -88,9 +86,9 @@ public class Startup } } -// In a controller, inject the policyRegistry and retrieve the policy: +// At the point of use, inject the policyRegistry and retrieve the policy: // (magic string "myCachePolicy" only hard-coded here to keep the example simple) -public MyController(IPolicyRegistry policyRegistry) +public MyController(IReadOnlyPolicyRegistry policyRegistry) { var _cachePolicy = policyRegistry.Get>("myCachePolicy"); // ... From 05ed4325a98bec7e0539da172f910344c998f537 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 26 Jan 2019 14:07:02 +0000 Subject: [PATCH 09/10] Add v3.0.0 doco --- CHANGELOG.md | 6 +++++- GitVersionConfig.yaml | 2 +- README.md | 6 ++++++ .../Properties/AssemblyInfo.cs | 6 +++--- .../Properties/AssemblyInfo.cs | 6 +++--- src/Polly.Caching.Memory.nuspec | 9 +++++++-- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37591e2..f15e262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -# Polly.Caching.MemoryCache change log +# Polly.Caching.Memory change log + +## 3.0.0 +- Allow caching of `default(TResult)` +- Compatible with Polly >= v7 ## 2.0.2 - No functional changes diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml index 02d54e2..aade6b1 100644 --- a/GitVersionConfig.yaml +++ b/GitVersionConfig.yaml @@ -1 +1 @@ -next-version: 2.0.2 \ No newline at end of file +next-version: 3.0.0 \ No newline at end of file diff --git a/README.md b/README.md index 0c772b6..bf33b53 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Polly.Caching.MemoryCache <v2.0 supports .NET4.0, .NET4.5 and .NetStandard 1. ## Versions and Dependencies +Polly.Caching.Memory >=v3.0 requires: + ++ [Polly](https://nuget.org/packages/polly) >= v7.0.0. ++ [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/) v2.0.2 or above (or v1.1.2, for NetStandard 1.3). + Polly.Caching.Memory >=v2.0.1 and <v3 requires: + [Polly](https://nuget.org/packages/polly) >= v6.1.1 and <v7. @@ -115,6 +120,7 @@ For details of changes by release see the [change log](CHANGELOG.md). * [@seanfarrow](https://github.com/seanfarrow) and [@reisenberger](https://github.com/reisenberger) - Initial caching architecture in the main Polly repo * [@kesmy](https://github.com/kesmy) - original structuring of the build for msbuild15, in the main Polly repo * [@seanfarrow](https://github.com/seanfarrow) - v2.0 update to Signed packages only to correspond with Polly v6.0.1 +* [@reisenberger](https://github.com/reisenberger) - Update to Polly v7.0.0 # Instructions for Contributing diff --git a/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs b/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs index 771f2b5..0ee7592 100644 --- a/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs +++ b/src/Polly.Caching.Memory.NetStandard13/Properties/AssemblyInfo.cs @@ -3,9 +3,9 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Polly.Caching.Memory")] -[assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.2.0")] -[assembly: AssemblyInformationalVersion("2.0.2.0")] +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] +[assembly: AssemblyInformationalVersion("3.0.0.0")] [assembly: CLSCompliant(false)] // Because Microsoft.Extensions.Caching.Memory.MemoryCache, on which Polly.Caching.MemoryCache.NetStandard13 depends, is not CLSCompliant. [assembly: InternalsVisibleTo("Polly.Caching.Memory.NetStandard13.Specs")] \ No newline at end of file diff --git a/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs b/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs index a8bea94..bc45d49 100644 --- a/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs +++ b/src/Polly.Caching.Memory.NetStandard20/Properties/AssemblyInfo.cs @@ -3,9 +3,9 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Polly.Caching.Memory")] -[assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.2.0")] -[assembly: AssemblyInformationalVersion("2.0.2.0")] +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] +[assembly: AssemblyInformationalVersion("3.0.0.0")] [assembly: CLSCompliant(false)] // Because Microsoft.Extensions.Caching.Memory.MemoryCache, on which Polly.Caching.MemoryCache.NetStandard13 depends, is not CLSCompliant. [assembly: InternalsVisibleTo("Polly.Caching.Memory.NetStandard20.Specs")] \ No newline at end of file diff --git a/src/Polly.Caching.Memory.nuspec b/src/Polly.Caching.Memory.nuspec index 8f3268c..f0826c1 100644 --- a/src/Polly.Caching.Memory.nuspec +++ b/src/Polly.Caching.Memory.nuspec @@ -13,6 +13,11 @@ Polly Cache Caching Cache-aside Copyright © 2019, App vNext + 3.0.0 + --------------------- + - Allow caching of default(TResult) + - Compatible with Polly >= v7 + 2.0.2 --------------------- - No functional changes @@ -53,11 +58,11 @@ - + - + From 46edf317c588f5c8fe118dd36fb49eaab7678ff8 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 9 Feb 2019 22:45:52 +0000 Subject: [PATCH 10/10] State System.ValueTuple dependency for Net Standard 1.1 target --- src/Polly.Caching.Memory.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Polly.Caching.Memory.nuspec b/src/Polly.Caching.Memory.nuspec index f0826c1..09c1554 100644 --- a/src/Polly.Caching.Memory.nuspec +++ b/src/Polly.Caching.Memory.nuspec @@ -60,6 +60,7 @@ +