From 831cf88d3a83ff9f35316eefe0ce502db378f326 Mon Sep 17 00:00:00 2001 From: Andrew Warren-Love Date: Mon, 11 Dec 2017 09:40:38 -0500 Subject: [PATCH 01/11] Add a generic ITtlStrategy so the strategy can depend on the result of the execution --- src/Polly.Shared/Caching/CacheEngine.cs | 4 +- src/Polly.Shared/Caching/CacheEngineAsync.cs | 4 +- src/Polly.Shared/Caching/CachePolicy.cs | 4 +- src/Polly.Shared/Caching/CachePolicyAsync.cs | 4 +- .../Caching/CacheTResultSyntax.cs | 20 ++++----- .../Caching/CacheTResultSyntaxAsync.cs | 20 ++++----- src/Polly.Shared/Caching/ContextualTtl.cs | 3 +- .../Caching/GenericTtlStrategy.cs | 33 +++++++++++++++ src/Polly.Shared/Caching/ITtlStrategy.cs | 13 +++++- src/Polly.Shared/Caching/NonSlidingTtl.cs | 3 +- src/Polly.Shared/Caching/ResultTtl.cs | 38 +++++++++++++++++ src/Polly.Shared/Caching/SlidingTtl.cs | 3 +- .../Caching/TtlStrategyExtensions.cs | 19 +++++++++ src/Polly.Shared/Polly.Shared.projitems | 3 ++ .../Caching/AbsoluteTtlSpecs.cs | 4 +- .../Caching/CacheTResultAsyncSpecs.cs | 2 +- .../Caching/CacheTResultSpecs.cs | 2 +- .../Caching/ContextualTtlSpecs.cs | 8 ++-- .../Caching/RelativeTtlSpecs.cs | 2 +- .../Caching/ResultTtlSpecs.cs | 41 +++++++++++++++++++ .../Caching/SlidingTtlSpecs.cs | 2 +- .../Polly.SharedSpecs.projitems | 1 + 22 files changed, 190 insertions(+), 43 deletions(-) create mode 100644 src/Polly.Shared/Caching/GenericTtlStrategy.cs create mode 100644 src/Polly.Shared/Caching/ResultTtl.cs create mode 100644 src/Polly.Shared/Caching/TtlStrategyExtensions.cs create mode 100644 src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs diff --git a/src/Polly.Shared/Caching/CacheEngine.cs b/src/Polly.Shared/Caching/CacheEngine.cs index 50a9c421b9..39695843cb 100644 --- a/src/Polly.Shared/Caching/CacheEngine.cs +++ b/src/Polly.Shared/Caching/CacheEngine.cs @@ -7,7 +7,7 @@ internal static partial class CacheEngine { internal static TResult Implementation( ISyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Func action, Context context, @@ -48,7 +48,7 @@ internal static TResult Implementation( TResult result = action(context, cancellationToken); - Ttl ttl = ttlStrategy.GetTtl(context); + Ttl ttl = ttlStrategy.GetTtl(context, result); if (ttl.Timespan > TimeSpan.Zero) { try diff --git a/src/Polly.Shared/Caching/CacheEngineAsync.cs b/src/Polly.Shared/Caching/CacheEngineAsync.cs index e65abe6f7c..6db366bc91 100644 --- a/src/Polly.Shared/Caching/CacheEngineAsync.cs +++ b/src/Polly.Shared/Caching/CacheEngineAsync.cs @@ -8,7 +8,7 @@ internal static partial class CacheEngine { internal static async Task ImplementationAsync( IAsyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Func> action, Context context, @@ -50,7 +50,7 @@ internal static async Task ImplementationAsync( TResult result = await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext); - Ttl ttl = ttlStrategy.GetTtl(context); + Ttl ttl = ttlStrategy.GetTtl(context, result); if (ttl.Timespan > TimeSpan.Zero) { try diff --git a/src/Polly.Shared/Caching/CachePolicy.cs b/src/Polly.Shared/Caching/CachePolicy.cs index 23eb7b60d8..ec66958be0 100644 --- a/src/Polly.Shared/Caching/CachePolicy.cs +++ b/src/Polly.Shared/Caching/CachePolicy.cs @@ -55,7 +55,7 @@ public override TResult ExecuteInternal(Func( _syncCacheProvider.For(), - _ttlStrategy, + _ttlStrategy.For(), _cacheKeyStrategy, action, context, @@ -75,7 +75,7 @@ public partial class CachePolicy : Policy, ICachePolicy syncCacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, diff --git a/src/Polly.Shared/Caching/CachePolicyAsync.cs b/src/Polly.Shared/Caching/CachePolicyAsync.cs index 2a7bc03683..564bc022cc 100644 --- a/src/Polly.Shared/Caching/CachePolicyAsync.cs +++ b/src/Polly.Shared/Caching/CachePolicyAsync.cs @@ -47,7 +47,7 @@ public override Task ExecuteAsyncInternal(Func( _asyncCacheProvider.AsyncFor(), - _ttlStrategy, + _ttlStrategy.For(), _cacheKeyStrategy, action, context, @@ -65,7 +65,7 @@ public partial class CachePolicy { internal CachePolicy( IAsyncCacheProvider asyncCacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, diff --git a/src/Polly.Shared/Caching/CacheTResultSyntax.cs b/src/Polly.Shared/Caching/CacheTResultSyntax.cs index c9a44fc768..6b0993ade4 100644 --- a/src/Polly.Shared/Caching/CacheTResultSyntax.cs +++ b/src/Polly.Shared/Caching/CacheTResultSyntax.cs @@ -20,7 +20,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return Cache(cacheProvider.For(), new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -39,7 +39,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return Cache(cacheProvider.For(), ttlStrategy.For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -55,7 +55,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid /// cacheProvider public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) { - return Cache(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return Cache(cacheProvider, new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -70,7 +70,7 @@ public static CachePolicy Cache(ISyncCacheProvider ca /// The policy instance. /// cacheProvider /// ttlStrategy - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) { return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } @@ -92,7 +92,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + return Cache(cacheProvider.For(), new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); } /// @@ -113,7 +113,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), ttlStrategy, cacheKeyStrategy, onCacheError); + return Cache(cacheProvider.For(), ttlStrategy.For(), cacheKeyStrategy, onCacheError); } /// @@ -131,7 +131,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid /// cacheKeyStrategy public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) { - return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + return Cache(cacheProvider, new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); } /// @@ -148,7 +148,7 @@ public static CachePolicy Cache(ISyncCacheProvider ca /// cacheProvider /// ttlStrategy /// cacheKeyStrategy - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); @@ -186,7 +186,7 @@ public static CachePolicy Cache(ISyncCacheProvider ca /// onCachePutError public static CachePolicy Cache( ISyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, @@ -222,7 +222,7 @@ public static CachePolicy Cache( /// onCachePutError public static CachePolicy Cache( ISyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, diff --git a/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs b/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs index 9f2d6db8f2..e802511dbb 100644 --- a/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs +++ b/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs @@ -20,7 +20,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -39,7 +39,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy.For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -55,7 +55,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache /// cacheProvider public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) { - return CacheAsync(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return CacheAsync(cacheProvider, new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// @@ -70,7 +70,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProviderDelegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// cacheProvider /// ttlStrategy - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) { return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } @@ -92,7 +92,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); } /// @@ -113,7 +113,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, cacheKeyStrategy, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy.For(), cacheKeyStrategy, onCacheError); } /// @@ -131,7 +131,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache /// cacheProvider public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) { - return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + return CacheAsync(cacheProvider, new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); } /// @@ -148,7 +148,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvidercacheKeyStrategy /// ttlStrategy /// cacheProvider - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); @@ -186,7 +186,7 @@ public static CachePolicy CacheAsync(IAsyncCacheProvideronCachePutError public static CachePolicy CacheAsync( IAsyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, @@ -222,7 +222,7 @@ public static CachePolicy CacheAsync( /// onCachePutError public static CachePolicy CacheAsync( IAsyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, diff --git a/src/Polly.Shared/Caching/ContextualTtl.cs b/src/Polly.Shared/Caching/ContextualTtl.cs index decc829ba2..4c1bbb479a 100644 --- a/src/Polly.Shared/Caching/ContextualTtl.cs +++ b/src/Polly.Shared/Caching/ContextualTtl.cs @@ -24,8 +24,9 @@ public class ContextualTtl : ITtlStrategy /// Gets the TimeSpan for which to keep an item about to be cached, which may be influenced by data in the execution context. /// /// The execution context. + /// The execution result. /// TimeSpan. - public Ttl GetTtl(Context context) + public Ttl GetTtl(Context context, object result) { if (!context.ContainsKey(TimeSpanKey)) return _noTtl; bool sliding = context.ContainsKey(SlidingExpirationKey) ? context[SlidingExpirationKey] as bool? ?? false : false; diff --git a/src/Polly.Shared/Caching/GenericTtlStrategy.cs b/src/Polly.Shared/Caching/GenericTtlStrategy.cs new file mode 100644 index 0000000000..c5e4e671e8 --- /dev/null +++ b/src/Polly.Shared/Caching/GenericTtlStrategy.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Polly.Utilities; + +namespace Polly.Caching +{ + /// + /// Represents a expiring based on the execution result. + /// + internal class GenericTtlStrategy : ITtlStrategy + { + private readonly ITtlStrategy _wrappedTtlStrategy; + + internal GenericTtlStrategy(ITtlStrategy ttlStrategy) + { + if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); + + _wrappedTtlStrategy = ttlStrategy; + } + + /// + /// Gets a TTL for a cacheable item, given the current execution context and result. + /// + /// The execution context. + /// The execution result. + /// A representing the remaining Ttl of the cached item. + public Ttl GetTtl(Context context, TResult result) + { + return _wrappedTtlStrategy.GetTtl(context, (object)result); + } + } +} diff --git a/src/Polly.Shared/Caching/ITtlStrategy.cs b/src/Polly.Shared/Caching/ITtlStrategy.cs index 208c5971ce..c73f7fb946 100644 --- a/src/Polly.Shared/Caching/ITtlStrategy.cs +++ b/src/Polly.Shared/Caching/ITtlStrategy.cs @@ -5,13 +5,22 @@ namespace Polly.Caching /// /// Defines a strategy for providing time-to-live durations for cacheable results. /// - public interface ITtlStrategy + public interface ITtlStrategy : ITtlStrategy + { + + } + + /// + /// Defines a strategy for providing time-to-live durations for cacheable results. + /// + public interface ITtlStrategy { /// /// Gets a TTL for a cacheable item, given the current execution context. /// /// The execution context. + /// The execution result. /// A representing the remaining Ttl of the cached item. - Ttl GetTtl(Context context); + Ttl GetTtl(Context context, TResult result); } } diff --git a/src/Polly.Shared/Caching/NonSlidingTtl.cs b/src/Polly.Shared/Caching/NonSlidingTtl.cs index b3ba3857a6..730faddb32 100644 --- a/src/Polly.Shared/Caching/NonSlidingTtl.cs +++ b/src/Polly.Shared/Caching/NonSlidingTtl.cs @@ -28,8 +28,9 @@ protected NonSlidingTtl(DateTimeOffset absoluteExpirationTime) /// Gets a TTL for a cacheable item, given the current execution context. /// /// The execution context. + /// The execution result. /// A representing the remaining Ttl of the cached item. - public Ttl GetTtl(Context context) + public Ttl GetTtl(Context context, object result) { TimeSpan untilPointInTime = absoluteExpirationTime.Subtract(SystemClock.DateTimeOffsetUtcNow()); TimeSpan remaining = untilPointInTime > TimeSpan.Zero ? untilPointInTime : TimeSpan.Zero; diff --git a/src/Polly.Shared/Caching/ResultTtl.cs b/src/Polly.Shared/Caching/ResultTtl.cs new file mode 100644 index 0000000000..bd4f8252f5 --- /dev/null +++ b/src/Polly.Shared/Caching/ResultTtl.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Polly.Caching +{ + /// + /// Defines a ttl strategy which will cache items with some calculation from the result of the execution. + /// + + public class ResultTtl : ITtlStrategy + { + private readonly Func ttlFunc; + + /// + /// Constructs a new instance of the ttl strategy. + /// + /// The function to calculate the TTL for which cache items should be considered valid. + public ResultTtl(Func ttlFunc) + { + if (ttlFunc == null) throw new ArgumentNullException(nameof(ttlFunc)); + + this.ttlFunc = ttlFunc; + } + + /// + /// Gets a TTL for the cacheable item. + /// + /// The execution context. + /// The execution result. + /// A representing the remaining Ttl of the cached item. + + public Ttl GetTtl(Context context, TResult result) + { + return ttlFunc(result); + } + } +} diff --git a/src/Polly.Shared/Caching/SlidingTtl.cs b/src/Polly.Shared/Caching/SlidingTtl.cs index 6c78c0dc6e..2877d8a767 100644 --- a/src/Polly.Shared/Caching/SlidingTtl.cs +++ b/src/Polly.Shared/Caching/SlidingTtl.cs @@ -27,9 +27,10 @@ public SlidingTtl(TimeSpan slidingTtl) /// Gets a TTL for the cacheable item. /// /// The execution context. + /// The execution result. /// A representing the remaining Ttl of the cached item. - public Ttl GetTtl(Context context) + public Ttl GetTtl(Context context, object result) { return ttl; } diff --git a/src/Polly.Shared/Caching/TtlStrategyExtensions.cs b/src/Polly.Shared/Caching/TtlStrategyExtensions.cs new file mode 100644 index 0000000000..009dbcdae4 --- /dev/null +++ b/src/Polly.Shared/Caching/TtlStrategyExtensions.cs @@ -0,0 +1,19 @@ +namespace Polly.Caching +{ + /// + /// Class that provides helper methods for configuring TtlStrategies. + /// + public static class TtlStrategyExtensions + { + /// + /// Provides a strongly -typed version of the supplied + /// + /// The type the returned will handle. + /// The non-generic ttl strategy to wrap. + /// ITtlStrategy{TCacheFormat}. + public static ITtlStrategy For(this ITtlStrategy ttlStrategy) + { + return new GenericTtlStrategy(ttlStrategy); + } + } +} diff --git a/src/Polly.Shared/Polly.Shared.projitems b/src/Polly.Shared/Polly.Shared.projitems index 294203281c..4447fba44a 100644 --- a/src/Polly.Shared/Polly.Shared.projitems +++ b/src/Polly.Shared/Polly.Shared.projitems @@ -31,6 +31,7 @@ + @@ -39,10 +40,12 @@ + + diff --git a/src/Polly.SharedSpecs/Caching/AbsoluteTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/AbsoluteTtlSpecs.cs index e6534ea08c..8252e2c69e 100644 --- a/src/Polly.SharedSpecs/Caching/AbsoluteTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/AbsoluteTtlSpecs.cs @@ -38,7 +38,7 @@ public void Should_return_zero_ttl_if_configured_to_expire_in_past() { AbsoluteTtl ttlStrategy = new AbsoluteTtl(SystemClock.DateTimeOffsetUtcNow().Subtract(TimeSpan.FromTicks(1))); - ttlStrategy.GetTtl(new Context("someExecutionKey")).Timespan.Should().Be(TimeSpan.Zero); + ttlStrategy.GetTtl(new Context("someExecutionKey"), null).Timespan.Should().Be(TimeSpan.Zero); } [Fact] @@ -50,7 +50,7 @@ public void Should_return_timespan_reflecting_time_until_expiry() AbsoluteTtl ttlStrategy = new AbsoluteTtl(tomorrow); SystemClock.DateTimeOffsetUtcNow = () => today; - ttlStrategy.GetTtl(new Context("someExecutionKey")).Timespan.Should().Be(TimeSpan.FromDays(1)); + ttlStrategy.GetTtl(new Context("someExecutionKey"), null).Timespan.Should().Be(TimeSpan.FromDays(1)); } public void Dispose() diff --git a/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs index a187b4694a..999101076c 100644 --- a/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs @@ -201,7 +201,7 @@ public async Task Should_allow_custom_ICacheKeyStrategy() IAsyncCacheProvider stubCacheProvider = new StubCacheProvider(); ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.ExecutionKey + context["id"]); //CachePolicy cache = Policy.CacheAsync(stubCacheProvider, TimeSpan.MaxValue, cacheKeyStrategy); - CachePolicy cache = Policy.CacheAsync(stubCacheProvider.AsyncFor(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); + CachePolicy cache = Policy.CacheAsync(stubCacheProvider.AsyncFor(), new RelativeTtl(TimeSpan.MaxValue).For(), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); object person1 = new ResultClass(ResultPrimitive.Good, "person1"); await stubCacheProvider.PutAsync("person1", person1, new Ttl(TimeSpan.MaxValue), CancellationToken.None, false).ConfigureAwait(false); diff --git a/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs index d1908b9b40..8c26ea1b3e 100644 --- a/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs @@ -195,7 +195,7 @@ public void Should_allow_custom_ICacheKeyStrategy() ISyncCacheProvider stubCacheProvider = new StubCacheProvider(); ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.ExecutionKey + context["id"]); - CachePolicy cache = Policy.Cache(stubCacheProvider.For(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); + CachePolicy cache = Policy.Cache(stubCacheProvider.For(), new RelativeTtl(TimeSpan.MaxValue).For(), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); object person1 = new ResultClass(ResultPrimitive.Good, "person1"); stubCacheProvider.Put("person1", person1, new Ttl(TimeSpan.MaxValue)); diff --git a/src/Polly.SharedSpecs/Caching/ContextualTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/ContextualTtlSpecs.cs index 803d990237..ae8cb0735d 100644 --- a/src/Polly.SharedSpecs/Caching/ContextualTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/ContextualTtlSpecs.cs @@ -12,7 +12,7 @@ public class ContextualTtlSpecs [Fact] public void Should_return_zero_if_no_value_set_on_context() { - new ContextualTtl().GetTtl(new Context("someExecutionKey")).Timespan.Should().Be(TimeSpan.Zero); + new ContextualTtl().GetTtl(new Context("someExecutionKey"), null).Timespan.Should().Be(TimeSpan.Zero); } [Fact] @@ -22,7 +22,7 @@ public void Should_return_zero_if_invalid_value_set_on_context() contextData[ContextualTtl.TimeSpanKey] = new object(); Context context = new Context(String.Empty, contextData); - new ContextualTtl().GetTtl(context).Timespan.Should().Be(TimeSpan.Zero); + new ContextualTtl().GetTtl(context, null).Timespan.Should().Be(TimeSpan.Zero); } [Fact] @@ -33,7 +33,7 @@ public void Should_return_value_set_on_context() contextData[ContextualTtl.TimeSpanKey] = ttl; Context context = new Context(String.Empty, contextData); - Ttl gotTtl = new ContextualTtl().GetTtl(context); + Ttl gotTtl = new ContextualTtl().GetTtl(context, null); gotTtl.Timespan.Should().Be(ttl); gotTtl.SlidingExpiration.Should().BeFalse(); } @@ -46,7 +46,7 @@ public void Should_return_negative_value_set_on_context() contextData[ContextualTtl.TimeSpanKey] = ttl; Context context = new Context(String.Empty, contextData); - Ttl gotTtl = new ContextualTtl().GetTtl(context); + Ttl gotTtl = new ContextualTtl().GetTtl(context, null); gotTtl.Timespan.Should().Be(ttl); gotTtl.SlidingExpiration.Should().BeFalse(); } diff --git a/src/Polly.SharedSpecs/Caching/RelativeTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/RelativeTtlSpecs.cs index eaecd1af99..19f00d391b 100644 --- a/src/Polly.SharedSpecs/Caching/RelativeTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/RelativeTtlSpecs.cs @@ -40,7 +40,7 @@ public void Should_return_configured_timespan() RelativeTtl ttlStrategy = new RelativeTtl(ttl); - Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey")); + Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey"), null); retrieved.Timespan.Should().BeCloseTo(ttl); retrieved.SlidingExpiration.Should().BeFalse(); } diff --git a/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs new file mode 100644 index 0000000000..c4c1d81e48 --- /dev/null +++ b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using FluentAssertions; +using Polly.Caching; +using Xunit; + +namespace Polly.Specs.Caching +{ + public class ResultTtlSpecs + { + [Fact] + public void Should_throw_when_func_is_null() + { + Action configure = () => new ResultTtl(null); + + configure.ShouldThrow().And.ParamName.Should().Be("ttlFunc"); + } + + [Fact] + public void Should_not_throw_when_func_is_set() + { + Action configure = () => new ResultTtl((result) => new Ttl()); + + configure.ShouldNotThrow(); + } + + [Fact] + public void Should_return_func_result() + { + TimeSpan ttl = TimeSpan.FromMinutes(1); + Func func = (result) => { return new Ttl(ttl); }; + + ResultTtl ttlStrategy = new ResultTtl(func); + + Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey"), new { Ttl = ttl }); + retrieved.Timespan.Should().BeCloseTo(ttl); + retrieved.SlidingExpiration.Should().BeFalse(); + } + } +} diff --git a/src/Polly.SharedSpecs/Caching/SlidingTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/SlidingTtlSpecs.cs index 2bcdb5ef06..933515e64e 100644 --- a/src/Polly.SharedSpecs/Caching/SlidingTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/SlidingTtlSpecs.cs @@ -40,7 +40,7 @@ public void Should_return_configured_timespan() SlidingTtl ttlStrategy = new SlidingTtl(ttl); - Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey")); + Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey"), null); retrieved.Timespan.Should().Be(ttl); retrieved.SlidingExpiration.Should().BeTrue(); } diff --git a/src/Polly.SharedSpecs/Polly.SharedSpecs.projitems b/src/Polly.SharedSpecs/Polly.SharedSpecs.projitems index 60e28f62ef..0f222d2d40 100644 --- a/src/Polly.SharedSpecs/Polly.SharedSpecs.projitems +++ b/src/Polly.SharedSpecs/Polly.SharedSpecs.projitems @@ -25,6 +25,7 @@ + From 70f6f53371b6288a8719bd5c5b71d95b7650e269 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Wed, 20 Dec 2017 22:24:54 +0000 Subject: [PATCH 02/11] Refine cache handling of null-result-from-execution Make null/default(TResult) handling symmetrical across get and put. null is not worth caching, as get (and some third-party caches) treat null as meaning 'cache did not hold a value' --- src/Polly.Shared/Caching/CacheEngine.cs | 2 +- src/Polly.Shared/Caching/CacheEngineAsync.cs | 2 +- .../Caching/CacheAsyncSpecs.cs | 28 +++++++++++++++++ src/Polly.SharedSpecs/Caching/CacheSpecs.cs | 31 +++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/Polly.Shared/Caching/CacheEngine.cs b/src/Polly.Shared/Caching/CacheEngine.cs index 39695843cb..59a128a83a 100644 --- a/src/Polly.Shared/Caching/CacheEngine.cs +++ b/src/Polly.Shared/Caching/CacheEngine.cs @@ -49,7 +49,7 @@ internal static TResult Implementation( TResult result = action(context, cancellationToken); Ttl ttl = ttlStrategy.GetTtl(context, result); - if (ttl.Timespan > TimeSpan.Zero) + if (ttl.Timespan > TimeSpan.Zero && result != null && !result.Equals(default(TResult))) { try { diff --git a/src/Polly.Shared/Caching/CacheEngineAsync.cs b/src/Polly.Shared/Caching/CacheEngineAsync.cs index 6db366bc91..aa77a2c20c 100644 --- a/src/Polly.Shared/Caching/CacheEngineAsync.cs +++ b/src/Polly.Shared/Caching/CacheEngineAsync.cs @@ -51,7 +51,7 @@ internal static async Task ImplementationAsync( TResult result = await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext); Ttl ttl = ttlStrategy.GetTtl(context, result); - if (ttl.Timespan > TimeSpan.Zero) + if (ttl.Timespan > TimeSpan.Zero && result != null && !result.Equals(default(TResult))) { try { diff --git a/src/Polly.SharedSpecs/Caching/CacheAsyncSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheAsyncSpecs.cs index 6ca601cc7e..6dea7072c7 100644 --- a/src/Polly.SharedSpecs/Caching/CacheAsyncSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheAsyncSpecs.cs @@ -538,6 +538,34 @@ public async Task Should_execute_oncachemiss_and_oncacheput_if_cache_does_not_ho keyPassedToOnCachePut.Should().Be(executionKey); } + [Fact] + public async Task Should_execute_oncachemiss_but_not_oncacheput_if_cache_does_not_hold_value_and_returned_value_not_worth_caching() + { + const string valueToReturn = null; + + const string executionKey = "SomeExecutionKey"; + string keyPassedToOnCacheMiss = null; + string keyPassedToOnCachePut = null; + + Context contextToExecute = new Context(executionKey); + Context contextPassedToOnCacheMiss = null; + Context contextPassedToOnCachePut = null; + + Action noErrorHandling = (_, __, ___) => { }; + Action emptyDelegate = (_, __) => { }; + Action onCacheMiss = (ctx, key) => { contextPassedToOnCacheMiss = ctx; keyPassedToOnCacheMiss = key; }; + Action onCachePut = (ctx, key) => { contextPassedToOnCachePut = ctx; keyPassedToOnCachePut = key; }; + + IAsyncCacheProvider stubCacheProvider = new StubCacheProvider(); + CachePolicy cache = Policy.CacheAsync(stubCacheProvider, new RelativeTtl(TimeSpan.MaxValue), DefaultCacheKeyStrategy.Instance, emptyDelegate, onCacheMiss, onCachePut, noErrorHandling, noErrorHandling); + + ((string)await stubCacheProvider.GetAsync(executionKey, CancellationToken.None, false).ConfigureAwait(false)).Should().BeNull(); + (await cache.ExecuteAsync(async () => { await TaskHelper.EmptyTask.ConfigureAwait(false); return valueToReturn; }, contextToExecute).ConfigureAwait(false)).Should().Be(valueToReturn); + + contextPassedToOnCachePut.Should().BeNull(); + keyPassedToOnCachePut.Should().BeNull(); + } + [Fact] public async Task Should_not_execute_oncachemiss_if_dont_query_cache_because_cache_key_not_set() { diff --git a/src/Polly.SharedSpecs/Caching/CacheSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheSpecs.cs index 02e457454b..1df548e58f 100644 --- a/src/Polly.SharedSpecs/Caching/CacheSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheSpecs.cs @@ -522,6 +522,37 @@ public void Should_execute_oncachemiss_and_oncacheput_if_cache_does_not_hold_val keyPassedToOnCachePut.Should().Be(executionKey); } + [Fact] + public void Should_execute_oncachemiss_but_not_oncacheput_if_cache_does_not_hold_value_and_returned_value_not_worth_caching() + { + const string valueToReturn = null; + + const string executionKey = "SomeExecutionKey"; + string keyPassedToOnCacheMiss = null; + string keyPassedToOnCachePut = null; + + Context contextToExecute = new Context(executionKey); + Context contextPassedToOnCacheMiss = null; + Context contextPassedToOnCachePut = null; + + Action noErrorHandling = (_, __, ___) => { }; + Action emptyDelegate = (_, __) => { }; + Action onCacheMiss = (ctx, key) => { contextPassedToOnCacheMiss = ctx; keyPassedToOnCacheMiss = key; }; + Action onCachePut = (ctx, key) => { contextPassedToOnCachePut = ctx; keyPassedToOnCachePut = key; }; + + ISyncCacheProvider stubCacheProvider = new StubCacheProvider(); + CachePolicy cache = Policy.Cache(stubCacheProvider, new RelativeTtl(TimeSpan.MaxValue), DefaultCacheKeyStrategy.Instance, emptyDelegate, onCacheMiss, onCachePut, noErrorHandling, noErrorHandling); + + stubCacheProvider.Get(executionKey).Should().BeNull(); + cache.Execute(() => { return valueToReturn; }, contextToExecute).Should().Be(valueToReturn); + + contextPassedToOnCacheMiss.Should().BeSameAs(contextToExecute); + keyPassedToOnCacheMiss.Should().Be(executionKey); + + contextPassedToOnCachePut.Should().BeNull(); + keyPassedToOnCachePut.Should().BeNull(); + } + [Fact] public void Should_not_execute_oncachemiss_if_dont_query_cache_because_cache_key_not_set() { From 39cea6fa7243f9f8026680f9388aeed7387bcbad Mon Sep 17 00:00:00 2001 From: reisenberger Date: Wed, 20 Dec 2017 22:36:52 +0000 Subject: [PATCH 03/11] Start v5.7.0 doco --- CHANGELOG.md | 4 ++++ GitVersionConfig.yaml | 2 +- src/Polly.Net40Async.nuspec | 4 ++++ src/Polly.NetStandard11/Properties/AssemblyInfo.cs | 2 +- src/Polly.nuspec | 4 ++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e003080365..49480e5040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ + +## 5.7.0 +- Minor cache fixes + ## 5.6.1 - Extend PolicyWrap syntax with interfaces diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml index 7bd2f8b508..cd6af75723 100644 --- a/GitVersionConfig.yaml +++ b/GitVersionConfig.yaml @@ -1 +1 @@ -next-version: 5.6.1 \ No newline at end of file +next-version: 5.7.0 \ No newline at end of file diff --git a/src/Polly.Net40Async.nuspec b/src/Polly.Net40Async.nuspec index a49b51cb61..2394b5e767 100644 --- a/src/Polly.Net40Async.nuspec +++ b/src/Polly.Net40Async.nuspec @@ -15,6 +15,10 @@ v5.0 is a major release with significant new resilience policies: Timeout; Bulkhead Isolation; Fallback; Cache; and PolicyWrap. See release notes back to v5.0.0 for full details. + 5.7.0 + --------------------- + - Minor cache fixes + 5.6.1 --------------------- - Extend PolicyWrap syntax with interfaces diff --git a/src/Polly.NetStandard11/Properties/AssemblyInfo.cs b/src/Polly.NetStandard11/Properties/AssemblyInfo.cs index d36229ee17..55b87cb8fa 100644 --- a/src/Polly.NetStandard11/Properties/AssemblyInfo.cs +++ b/src/Polly.NetStandard11/Properties/AssemblyInfo.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Polly")] -[assembly: AssemblyVersion("5.6.1.0")] +[assembly: AssemblyVersion("5.7.0.0")] [assembly: CLSCompliant(true)] [assembly: InternalsVisibleTo("Polly.NetStandard11.Specs")] \ No newline at end of file diff --git a/src/Polly.nuspec b/src/Polly.nuspec index 23d3948c54..e36afcafa4 100644 --- a/src/Polly.nuspec +++ b/src/Polly.nuspec @@ -15,6 +15,10 @@ v5.0 is a major release with significant new resilience policies: Timeout; Bulkhead Isolation; Fallback; Cache; and PolicyWrap. See release notes back to v5.0.0 for full details. + 5.7.0 + --------------------- + - Minor cache fixes + 5.6.1 --------------------- - Extend PolicyWrap syntax with interfaces From f981455fd96603feade4e9f2ab5247bc7bf18880 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Wed, 20 Dec 2017 22:55:19 +0000 Subject: [PATCH 04/11] Make build script more robust Fix issue with order of directory cleaning in local-machine build runs --- build.cake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/build.cake b/build.cake index 3c136d1a36..6edcfc7e1c 100644 --- a/build.cake +++ b/build.cake @@ -1,4 +1,4 @@ -/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// // ARGUMENTS /////////////////////////////////////////////////////////////////////////////// @@ -92,12 +92,16 @@ Teardown(_ => Task("__Clean") .Does(() => { - CleanDirectories(new DirectoryPath[] { + DirectoryPath[] cleanDirectories = new DirectoryPath[] { buildDir, - artifactsDir, testResultsDir, + artifactsDir, nupkgDestDir - }); + }; + + CleanDirectories(cleanDirectories); + + foreach(var path in cleanDirectories) { EnsureDirectoryExists(path); } foreach(var path in solutionPaths) { From 724b0498f42270ba6a90176aa857e7aba4ca2a23 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Thu, 21 Dec 2017 08:37:23 +0000 Subject: [PATCH 05/11] Make build script more robust --- build.cake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index 6edcfc7e1c..7c124a5df1 100644 --- a/build.cake +++ b/build.cake @@ -95,8 +95,8 @@ Task("__Clean") DirectoryPath[] cleanDirectories = new DirectoryPath[] { buildDir, testResultsDir, - artifactsDir, - nupkgDestDir + nupkgDestDir, + artifactsDir }; CleanDirectories(cleanDirectories); From efbeb1661bc853317554741c534623010f0b8057 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Thu, 21 Dec 2017 08:41:15 +0000 Subject: [PATCH 06/11] Extend cache policy configuration overloads --- src/Polly.Shared/Caching/CacheSyntax.cs | 199 ++++- src/Polly.Shared/Caching/CacheSyntaxAsync.cs | 183 ++++- .../Caching/CacheTResultSyntax.cs | 680 ++++++++++++++++- .../Caching/CacheTResultSyntaxAsync.cs | 689 ++++++++++++++++-- .../Caching/GenericTtlStrategy.cs | 6 +- .../Caching/TtlStrategyExtensions.cs | 4 +- .../Caching/CacheTResultAsyncSpecs.cs | 2 +- .../Caching/CacheTResultSpecs.cs | 2 +- 8 files changed, 1670 insertions(+), 95 deletions(-) diff --git a/src/Polly.Shared/Caching/CacheSyntax.cs b/src/Polly.Shared/Caching/CacheSyntax.cs index 7ebca3dd61..b7aa2fb0c9 100644 --- a/src/Polly.Shared/Caching/CacheSyntax.cs +++ b/src/Polly.Shared/Caching/CacheSyntax.cs @@ -8,7 +8,7 @@ public partial class Policy /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -24,7 +24,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -41,7 +41,51 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy t /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); + if (cacheKeyStrategy == null) throw new ArgumentNullException(nameof(cacheKeyStrategy)); + + onCacheError = onCacheError ?? ((_, __, ___) => { }); + Action emptyDelegate = (_, __) => { }; + + return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -59,7 +103,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -82,10 +126,116 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy t return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); } + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// + /// + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// + /// + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// + /// + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -123,7 +273,44 @@ public static CachePolicy Cache( /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// + /// + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. diff --git a/src/Polly.Shared/Caching/CacheSyntaxAsync.cs b/src/Polly.Shared/Caching/CacheSyntaxAsync.cs index a793249c02..4ab422fc39 100644 --- a/src/Polly.Shared/Caching/CacheSyntaxAsync.cs +++ b/src/Polly.Shared/Caching/CacheSyntaxAsync.cs @@ -38,6 +38,50 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStra return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); + if (cacheKeyStrategy == null) throw new ArgumentNullException(nameof(cacheKeyStrategy)); + + onCacheError = onCacheError ?? ((_, __, ___) => { }); + Action emptyDelegate = (_, __) => { }; + + return new CachePolicy(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . @@ -82,6 +126,106 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStra return new CachePolicy(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); } + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key. + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key. + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . @@ -106,8 +250,8 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStra /// onCacheGetError /// onCachePutError public static CachePolicy CacheAsync( - IAsyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, @@ -118,6 +262,41 @@ public static CachePolicy CacheAsync( return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } + /// + /// Builds a that will function like a result cache for delegate executions returning a result. + /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + /// /// Builds a that will function like a result cache for delegate executions returning a result. /// Before executing a delegate returning a result, checks whether the holds a value for the cache key determined by applying the to the execution . diff --git a/src/Polly.Shared/Caching/CacheTResultSyntax.cs b/src/Polly.Shared/Caching/CacheTResultSyntax.cs index 6b0993ade4..3467c9c8c8 100644 --- a/src/Polly.Shared/Caching/CacheTResultSyntax.cs +++ b/src/Polly.Shared/Caching/CacheTResultSyntax.cs @@ -8,7 +8,7 @@ public partial class Policy /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -20,13 +20,13 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return Cache(cacheProvider.For(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -39,46 +39,54 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), ttlStrategy.For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return Cache(cacheProvider.For(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// - /// Builds a that will function like a result cache for delegate executions returning a . - /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// Duration (ttl) for which to cache values. + /// The cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// The policy instance. /// cacheProvider - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) { - return Cache(cacheProvider, new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); } /// - /// Builds a that will function like a result cache for delegate executions returning a . - /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// The policy instance. /// cacheProvider /// ttlStrategy - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) { - return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -92,13 +100,13 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); + return Cache(cacheProvider.For(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -113,58 +121,194 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvid { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return Cache(cacheProvider.For(), ttlStrategy.For(), cacheKeyStrategy, onCacheError); + return Cache(cacheProvider.For(), ttlStrategy, cacheKeyStrategy, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// Duration (ttl) for which to cache values. /// The cache key strategy. - /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. /// The policy instance. /// cacheProvider /// cacheKeyStrategy - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) { - return Cache(cacheProvider, new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// A strategy for specifying ttl for values to be cached. /// The cache key strategy. - /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. /// The policy instance. /// cacheProvider /// ttlStrategy /// cacheKeyStrategy - public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); - if (cacheKeyStrategy == null) throw new ArgumentNullException(nameof(cacheKeyStrategy)); - onCacheError = onCacheError ?? ((_, __, ___) => { }); + return Cache(cacheProvider.For(), ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } - Action emptyDelegate = (_, __) => { }; + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return new CachePolicy(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + return Cache(cacheProvider.For(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -185,22 +329,486 @@ public static CachePolicy Cache(ISyncCacheProvider ca /// onCacheGetError /// onCachePutError public static CachePolicy Cache( - ISyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, - ICacheKeyStrategy cacheKeyStrategy, + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, Action onCachePut, Action onCacheGetError, Action onCachePutError) { - return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return Cache(cacheProvider.For(), ttlStrategy, cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) + { + return Cache(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + { + return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + { + return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return Cache(cacheProvider, ttlStrategy.For(), cacheKeyStrategy.GetCacheKey, + emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, + onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return Cache(cacheProvider, ttlStrategy.For(), cacheKeyStrategy, + emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, + onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy Cache( + ISyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return Cache(cacheProvider, ttlStrategy.For(), cacheKeyStrategy, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the contains a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. diff --git a/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs b/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs index e802511dbb..762c4ace1d 100644 --- a/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs +++ b/src/Polly.Shared/Caching/CacheTResultSyntaxAsync.cs @@ -8,7 +8,7 @@ public partial class Policy /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -20,13 +20,13 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -39,46 +39,54 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy.For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); } /// - /// Builds a that will function like a result cache for delegate executions returning a . - /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// Duration (ttl) for which to cache values. + /// The cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// The policy instance. /// cacheProvider - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) { - return CacheAsync(cacheProvider, new RelativeTtl(ttl).For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); } /// - /// Builds a that will function like a result cache for delegate executions returning a . - /// Before executing a delegate, checks whether the holds a value for the cache key specified by . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// A strategy for specifying ttl for values to be cached. - /// The policy instance. + /// The cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. /// cacheProvider /// ttlStrategy - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) { - return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -86,19 +94,19 @@ public static CachePolicy CacheAsync(IAsyncCacheProviderThe cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// The policy instance. - /// cacheKeyStrategy /// cacheProvider + /// cacheKeyStrategy public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -106,65 +114,201 @@ public static CachePolicy CacheAsync(IAsyncCacheProvider cache /// The cache key strategy. /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. /// The policy instance. - /// cacheKeyStrategy - /// ttlStrategy /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy.For(), cacheKeyStrategy, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, cacheKeyStrategy, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// Duration (ttl) for which to cache values. /// The cache key strategy. - /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. /// The policy instance. - /// cacheKeyStrategy /// cacheProvider - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) { - return CacheAsync(cacheProvider, new RelativeTtl(ttl).For(), cacheKeyStrategy, onCacheError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. /// A strategy for specifying ttl for values to be cached. /// The cache key strategy. - /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. /// The policy instance. - /// cacheKeyStrategy - /// ttlStrategy /// cacheProvider - public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) { if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); - if (cacheKeyStrategy == null) throw new ArgumentNullException(nameof(cacheKeyStrategy)); - onCacheError = onCacheError ?? ((_, __, ___) => { }); + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } - Action emptyDelegate = (_, __) => { }; + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); - return new CachePolicy(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + return CacheAsync(cacheProvider.AsyncFor(), new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. @@ -185,22 +329,481 @@ public static CachePolicy CacheAsync(IAsyncCacheProvideronCacheGetError /// onCachePutError public static CachePolicy CacheAsync( - IAsyncCacheProvider cacheProvider, - ITtlStrategy ttlStrategy, - ICacheKeyStrategy cacheKeyStrategy, + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Func cacheKeyStrategy, Action onCacheGet, Action onCacheMiss, Action onCachePut, Action onCacheGetError, Action onCachePutError) { - return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + if (cacheProvider == null) throw new ArgumentNullException(nameof(cacheProvider)); + + return CacheAsync(cacheProvider.AsyncFor(), ttlStrategy, cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Action onCacheError = null) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + { + return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key specified by . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Action onCacheError = null) + { + return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, Func cacheKeyStrategy, Action onCacheError = null) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + public static CachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action onCacheError = null) + { + onCacheError = onCacheError ?? ((_, __, ___) => { }); + + Action emptyDelegate = (_, __) => { }; + + return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, onCacheError, onCacheError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy.For(), DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy, DefaultCacheKeyStrategy.Instance.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy.For(), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + ICacheKeyStrategy cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// Duration (ttl) for which to cache values. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + TimeSpan ttl, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy, onCacheGet, onCacheMiss, + onCachePut, onCacheGetError, onCachePutError); + } + + /// + /// Builds a that will function like a result cache for delegate executions returning a . + /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// + /// + /// The cache provider. + /// A strategy for specifying ttl for values to be cached. + /// The cache key strategy. + /// Delegate to call on a cache hit, when value is returned from cache. + /// Delegate to call on a cache miss. + /// Delegate to call on cache put. + /// Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception. + /// Delegate to call if an exception is thrown when attempting to put a value in the cache, passing the execution context, the cache key, and the exception. + /// The policy instance. + /// cacheProvider + /// ttlStrategy + /// cacheKeyStrategy + /// onCacheGet + /// onCacheMiss + /// onCachePut + /// onCacheGetError + /// onCachePutError + public static CachePolicy CacheAsync( + IAsyncCacheProvider cacheProvider, + ITtlStrategy ttlStrategy, + Func cacheKeyStrategy, + Action onCacheGet, + Action onCacheMiss, + Action onCachePut, + Action onCacheGetError, + Action onCachePutError) + { + return CacheAsync(cacheProvider, ttlStrategy.For(), cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); } /// /// Builds a that will function like a result cache for delegate executions returning a . /// Before executing a delegate, checks whether the holds a value for the cache key determined by applying the to the execution . - /// If the provides a value, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. + /// If the provides a value from cache, returns that value and does not execute the governed delegate. If the does not provide a value, executes the governed delegate, stores the value with the , then returns the value. /// /// /// The cache provider. diff --git a/src/Polly.Shared/Caching/GenericTtlStrategy.cs b/src/Polly.Shared/Caching/GenericTtlStrategy.cs index c5e4e671e8..906b2f0032 100644 --- a/src/Polly.Shared/Caching/GenericTtlStrategy.cs +++ b/src/Polly.Shared/Caching/GenericTtlStrategy.cs @@ -6,7 +6,7 @@ namespace Polly.Caching { /// - /// Represents a expiring based on the execution result. + /// Represents a strongly-typed wrapper of a non-generic strategy. /// internal class GenericTtlStrategy : ITtlStrategy { @@ -14,9 +14,7 @@ internal class GenericTtlStrategy : ITtlStrategy internal GenericTtlStrategy(ITtlStrategy ttlStrategy) { - if (ttlStrategy == null) throw new ArgumentNullException(nameof(ttlStrategy)); - - _wrappedTtlStrategy = ttlStrategy; + _wrappedTtlStrategy = ttlStrategy ?? throw new ArgumentNullException(nameof(ttlStrategy)); } /// diff --git a/src/Polly.Shared/Caching/TtlStrategyExtensions.cs b/src/Polly.Shared/Caching/TtlStrategyExtensions.cs index 009dbcdae4..56d51dda19 100644 --- a/src/Polly.Shared/Caching/TtlStrategyExtensions.cs +++ b/src/Polly.Shared/Caching/TtlStrategyExtensions.cs @@ -3,7 +3,7 @@ /// /// Class that provides helper methods for configuring TtlStrategies. /// - public static class TtlStrategyExtensions + internal static class TtlStrategyExtensions { /// /// Provides a strongly -typed version of the supplied @@ -11,7 +11,7 @@ public static class TtlStrategyExtensions /// The type the returned will handle. /// The non-generic ttl strategy to wrap. /// ITtlStrategy{TCacheFormat}. - public static ITtlStrategy For(this ITtlStrategy ttlStrategy) + internal static ITtlStrategy For(this ITtlStrategy ttlStrategy) { return new GenericTtlStrategy(ttlStrategy); } diff --git a/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs index 999101076c..a187b4694a 100644 --- a/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheTResultAsyncSpecs.cs @@ -201,7 +201,7 @@ public async Task Should_allow_custom_ICacheKeyStrategy() IAsyncCacheProvider stubCacheProvider = new StubCacheProvider(); ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.ExecutionKey + context["id"]); //CachePolicy cache = Policy.CacheAsync(stubCacheProvider, TimeSpan.MaxValue, cacheKeyStrategy); - CachePolicy cache = Policy.CacheAsync(stubCacheProvider.AsyncFor(), new RelativeTtl(TimeSpan.MaxValue).For(), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); + CachePolicy cache = Policy.CacheAsync(stubCacheProvider.AsyncFor(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); object person1 = new ResultClass(ResultPrimitive.Good, "person1"); await stubCacheProvider.PutAsync("person1", person1, new Ttl(TimeSpan.MaxValue), CancellationToken.None, false).ConfigureAwait(false); diff --git a/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs b/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs index 8c26ea1b3e..d1908b9b40 100644 --- a/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/CacheTResultSpecs.cs @@ -195,7 +195,7 @@ public void Should_allow_custom_ICacheKeyStrategy() ISyncCacheProvider stubCacheProvider = new StubCacheProvider(); ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.ExecutionKey + context["id"]); - CachePolicy cache = Policy.Cache(stubCacheProvider.For(), new RelativeTtl(TimeSpan.MaxValue).For(), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); + CachePolicy cache = Policy.Cache(stubCacheProvider.For(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling); object person1 = new ResultClass(ResultPrimitive.Good, "person1"); stubCacheProvider.Put("person1", person1, new Ttl(TimeSpan.MaxValue)); From a10dbd2f78291f5764e0923958ac5ca80b136d38 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Tue, 2 Jan 2018 14:27:29 +0000 Subject: [PATCH 07/11] Permit custom policies (#391) * Permit user-defined custom policies + Change constructors of `Policy` and `Policy` base classes from `internal` to `protected`. + Make `ExceptionPredicate` and `ResultPredicate` classes `public` (necessary to allow users to create custom policies responding to faults declared in handle clauses) --- CHANGELOG.md | 1 + src/Polly.Net40Async.nuspec | 1 + src/Polly.Shared/ExceptionPredicate.cs | 7 ++++++- src/Polly.Shared/Policy.TResult.cs | 8 +++++++- src/Polly.Shared/Policy.cs | 7 ++++++- src/Polly.Shared/PolicyAsync.TResult.cs | 8 +++++++- src/Polly.Shared/PolicyAsync.cs | 7 ++++++- src/Polly.Shared/ResultPredicate.cs | 9 ++++++++- src/Polly.nuspec | 1 + 9 files changed, 43 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49480e5040..9fb8e5fd7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 5.7.0 - Minor cache fixes +- Allow user-created custom policies ## 5.6.1 - Extend PolicyWrap syntax with interfaces diff --git a/src/Polly.Net40Async.nuspec b/src/Polly.Net40Async.nuspec index 2394b5e767..eae33370e4 100644 --- a/src/Polly.Net40Async.nuspec +++ b/src/Polly.Net40Async.nuspec @@ -18,6 +18,7 @@ 5.7.0 --------------------- - Minor cache fixes + - Allow user-created custom policies 5.6.1 --------------------- diff --git a/src/Polly.Shared/ExceptionPredicate.cs b/src/Polly.Shared/ExceptionPredicate.cs index 138abac68b..03cc9dfd4d 100644 --- a/src/Polly.Shared/ExceptionPredicate.cs +++ b/src/Polly.Shared/ExceptionPredicate.cs @@ -2,5 +2,10 @@ namespace Polly { - internal delegate Exception ExceptionPredicate(Exception ex); + /// + /// A predicate that can be run against a passed . + /// + /// The passed exception, against which to evaluate the predicate. + /// A matched ; or null, if an exception was not matched. ExceptionPredicate implementations may return the passed Exception , indicating that it matched the predicate. They may also return inner exceptions of the passed Exception , to indicate that the returned inner exception matched the predicate. + public delegate Exception ExceptionPredicate(Exception ex); } \ No newline at end of file diff --git a/src/Polly.Shared/Policy.TResult.cs b/src/Polly.Shared/Policy.TResult.cs index d9873a4de9..7fb7f8560d 100644 --- a/src/Polly.Shared/Policy.TResult.cs +++ b/src/Polly.Shared/Policy.TResult.cs @@ -16,7 +16,13 @@ public abstract partial class Policy : ISyncPolicy internal IEnumerable ExceptionPredicates { get; } internal IEnumerable> ResultPredicates { get; } - internal Policy( + /// + /// Constructs a new instance of a derived type with the passed , and + /// + /// The execution policy that will be applied to delegates executed synchronously through the policy. + /// Predicates indicating which exceptions the policy should handle. + /// Predicates indicating which results the policy should handle. + protected Policy( Func, Context, CancellationToken, TResult> executionPolicy, IEnumerable exceptionPredicates, IEnumerable> resultPredicates diff --git a/src/Polly.Shared/Policy.cs b/src/Polly.Shared/Policy.cs index a0ff568ad7..fe4a84b20c 100644 --- a/src/Polly.Shared/Policy.cs +++ b/src/Polly.Shared/Policy.cs @@ -16,7 +16,12 @@ public abstract partial class Policy : ISyncPolicy private readonly Action, Context, CancellationToken> _exceptionPolicy; internal IEnumerable ExceptionPredicates { get; } - internal Policy( + /// + /// Constructs a new instance of a derived type with the passed and + /// + /// The execution policy that will be applied to delegates executed synchronously through the policy. + /// Predicates indicating which exceptions the policy should handle. + protected Policy( Action, Context, CancellationToken> exceptionPolicy, IEnumerable exceptionPredicates) { diff --git a/src/Polly.Shared/PolicyAsync.TResult.cs b/src/Polly.Shared/PolicyAsync.TResult.cs index 7320b36c27..6f92e520d9 100644 --- a/src/Polly.Shared/PolicyAsync.TResult.cs +++ b/src/Polly.Shared/PolicyAsync.TResult.cs @@ -12,7 +12,13 @@ public abstract partial class Policy : IAsyncPolicy { private readonly Func>, Context, CancellationToken, bool, Task> _asyncExecutionPolicy; - internal Policy( + /// + /// Constructs a new instance of a derived type with the passed , and + /// + /// The execution policy that will be applied to delegates executed asychronously through the asynchronous policy. + /// Predicates indicating which exceptions the policy should handle. + /// Predicates indicating which results the policy should handle. + protected Policy( Func>, Context, CancellationToken, bool, Task> asyncExecutionPolicy, IEnumerable exceptionPredicates, IEnumerable> resultPredicates) diff --git a/src/Polly.Shared/PolicyAsync.cs b/src/Polly.Shared/PolicyAsync.cs index 6e3a6153b1..b29721cbd0 100644 --- a/src/Polly.Shared/PolicyAsync.cs +++ b/src/Polly.Shared/PolicyAsync.cs @@ -11,7 +11,12 @@ public abstract partial class Policy : IAsyncPolicy { private readonly Func, Context, CancellationToken, bool, Task> _asyncExceptionPolicy; - internal Policy( + /// + /// Constructs a new instance of a derived type with the passed and . + /// + /// The execution policy that will be applied to delegates executed asychronously through the asynchronous policy. + /// Predicates indicating which exceptions the policy should handle. + protected Policy( Func, Context, CancellationToken, bool, Task> asyncExceptionPolicy, IEnumerable exceptionPredicates) { diff --git a/src/Polly.Shared/ResultPredicate.cs b/src/Polly.Shared/ResultPredicate.cs index e41ff29bc5..0821def18a 100644 --- a/src/Polly.Shared/ResultPredicate.cs +++ b/src/Polly.Shared/ResultPredicate.cs @@ -1,4 +1,11 @@ namespace Polly { - internal delegate bool ResultPredicate(TResult result); + /// + /// A predicate that can be run against a passed result value of type . + /// + /// The passed result, against which to evaluate the predicate. + /// The type of results which this predicate can evaluate. + /// True if the passed matched the predicate; otherwise, false. + + public delegate bool ResultPredicate(TResult result); } \ No newline at end of file diff --git a/src/Polly.nuspec b/src/Polly.nuspec index e36afcafa4..55f394260f 100644 --- a/src/Polly.nuspec +++ b/src/Polly.nuspec @@ -18,6 +18,7 @@ 5.7.0 --------------------- - Minor cache fixes + - Allow user-created custom policies 5.6.1 --------------------- From 278ba7813e9d89e597fb42f997c7a4da68eb89fe Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 6 Jan 2018 11:36:14 +0000 Subject: [PATCH 08/11] Match code conventions --- src/Polly.Shared/Caching/ResultTtl.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Polly.Shared/Caching/ResultTtl.cs b/src/Polly.Shared/Caching/ResultTtl.cs index bd4f8252f5..1badfad1f7 100644 --- a/src/Polly.Shared/Caching/ResultTtl.cs +++ b/src/Polly.Shared/Caching/ResultTtl.cs @@ -10,7 +10,7 @@ namespace Polly.Caching public class ResultTtl : ITtlStrategy { - private readonly Func ttlFunc; + private readonly Func _ttlFunc; /// /// Constructs a new instance of the ttl strategy. @@ -18,9 +18,7 @@ public class ResultTtl : ITtlStrategy /// The function to calculate the TTL for which cache items should be considered valid. public ResultTtl(Func ttlFunc) { - if (ttlFunc == null) throw new ArgumentNullException(nameof(ttlFunc)); - - this.ttlFunc = ttlFunc; + _ttlFunc = ttlFunc ?? throw new ArgumentNullException(nameof(ttlFunc)); } /// @@ -32,7 +30,7 @@ public ResultTtl(Func ttlFunc) public Ttl GetTtl(Context context, TResult result) { - return ttlFunc(result); + return _ttlFunc(result); } } } From d978a49224df9021dfe1679561d38910fd9850db Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 6 Jan 2018 11:40:57 +0000 Subject: [PATCH 09/11] Refine ResultTtlSpecs Make spec demonstrate that Ttl can actually be based on the incoming result. --- src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs index c4c1d81e48..69fcdb8a0f 100644 --- a/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs @@ -1,8 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using FluentAssertions; using Polly.Caching; +using Polly.Specs.Helpers.Caching; using Xunit; namespace Polly.Specs.Caching @@ -12,7 +11,7 @@ public class ResultTtlSpecs [Fact] public void Should_throw_when_func_is_null() { - Action configure = () => new ResultTtl(null); + Action configure = () => new ResultTtl(null); configure.ShouldThrow().And.ParamName.Should().Be("ttlFunc"); } @@ -20,7 +19,7 @@ public void Should_throw_when_func_is_null() [Fact] public void Should_not_throw_when_func_is_set() { - Action configure = () => new ResultTtl((result) => new Ttl()); + Action configure = () => new ResultTtl((result) => new Ttl()); configure.ShouldNotThrow(); } @@ -29,13 +28,14 @@ public void Should_not_throw_when_func_is_set() public void Should_return_func_result() { TimeSpan ttl = TimeSpan.FromMinutes(1); - Func func = (result) => { return new Ttl(ttl); }; + Func func = (result) => { return new Ttl(result.Ttl); }; ResultTtl ttlStrategy = new ResultTtl(func); Ttl retrieved = ttlStrategy.GetTtl(new Context("someExecutionKey"), new { Ttl = ttl }); - retrieved.Timespan.Should().BeCloseTo(ttl); + retrieved.Timespan.Should().Be(ttl); retrieved.SlidingExpiration.Should().BeFalse(); } + } } From 31ccf1c9305b7fbf6ba4f427f07192173472fba8 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 6 Jan 2018 11:58:18 +0000 Subject: [PATCH 10/11] Allow ResultTtl to take context as input param --- src/Polly.Shared/Caching/ResultTtl.cs | 20 ++++++++--- .../Caching/ResultTtlSpecs.cs | 33 +++++++++++++++++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/Polly.Shared/Caching/ResultTtl.cs b/src/Polly.Shared/Caching/ResultTtl.cs index 1badfad1f7..1c4c153a04 100644 --- a/src/Polly.Shared/Caching/ResultTtl.cs +++ b/src/Polly.Shared/Caching/ResultTtl.cs @@ -5,18 +5,28 @@ namespace Polly.Caching { /// - /// Defines a ttl strategy which will cache items with some calculation from the result of the execution. + /// Defines a ttl strategy which can calculate a duration to cache items dynamically based on the execution context and result of the execution. /// - + /// The type of results that the ttl calculation function will take as an input parameter. public class ResultTtl : ITtlStrategy { - private readonly Func _ttlFunc; + private readonly Func _ttlFunc; /// - /// Constructs a new instance of the ttl strategy. + /// Constructs a new instance of the ttl strategy, with a func calculating based on the value to cache. /// /// The function to calculate the TTL for which cache items should be considered valid. public ResultTtl(Func ttlFunc) + { + if (ttlFunc == null) throw new ArgumentNullException(nameof(ttlFunc)); + _ttlFunc = (context, result) => ttlFunc(result); + } + + /// + /// Constructs a new instance of the ttl strategy, with a func calculating based on the execution and value to cache. + /// + /// The function to calculate the TTL for which cache items should be considered valid. + public ResultTtl(Func ttlFunc) { _ttlFunc = ttlFunc ?? throw new ArgumentNullException(nameof(ttlFunc)); } @@ -30,7 +40,7 @@ public ResultTtl(Func ttlFunc) public Ttl GetTtl(Context context, TResult result) { - return _ttlFunc(result); + return _ttlFunc(context, result); } } } diff --git a/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs index 69fcdb8a0f..1e9b78ceb5 100644 --- a/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs +++ b/src/Polly.SharedSpecs/Caching/ResultTtlSpecs.cs @@ -11,7 +11,15 @@ public class ResultTtlSpecs [Fact] public void Should_throw_when_func_is_null() { - Action configure = () => new ResultTtl(null); + Action configure = () => new ResultTtl((Func)null); + + configure.ShouldThrow().And.ParamName.Should().Be("ttlFunc"); + } + + [Fact] + public void Should_throw_when_func_is_null_using_context() + { + Action configure = () => new ResultTtl((Func)null); configure.ShouldThrow().And.ParamName.Should().Be("ttlFunc"); } @@ -24,6 +32,14 @@ public void Should_not_throw_when_func_is_set() configure.ShouldNotThrow(); } + [Fact] + public void Should_not_throw_when_func_is_set_using_context() + { + Action configure = () => new ResultTtl((context, result) => new Ttl()); + + configure.ShouldNotThrow(); + } + [Fact] public void Should_return_func_result() { @@ -36,6 +52,19 @@ public void Should_return_func_result() retrieved.Timespan.Should().Be(ttl); retrieved.SlidingExpiration.Should().BeFalse(); } - + + [Fact] + public void Should_return_func_result_using_context() + { + const string specialKey = "specialKey"; + + TimeSpan ttl = TimeSpan.FromMinutes(1); + Func func = (context, result) => { return context.ExecutionKey == specialKey ? new Ttl(TimeSpan.Zero) : new Ttl(result.Ttl); }; + + ResultTtl ttlStrategy = new ResultTtl(func); + + ttlStrategy.GetTtl(new Context("someExecutionKey"), new { Ttl = ttl }).Timespan.Should().Be(ttl); + ttlStrategy.GetTtl(new Context(specialKey), new { Ttl = ttl }).Timespan.Should().Be(TimeSpan.Zero); + } } } From 8ccd9451eb1745b98cc8368c5cfe13b670607db9 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Sat, 6 Jan 2018 11:58:59 +0000 Subject: [PATCH 11/11] Add v5.7.0 doco for ResultTtl --- CHANGELOG.md | 1 + README.md | 1 + src/Polly.Net40Async.nuspec | 1 + src/Polly.nuspec | 1 + 4 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49480e5040..099c689165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 5.7.0 - Minor cache fixes +- Add ability to calculate cache Ttl based on item to cache ## 5.6.1 - Extend PolicyWrap syntax with interfaces diff --git a/README.md b/README.md index f2e8daa0bf..95ddf3dc0d 100644 --- a/README.md +++ b/README.md @@ -947,6 +947,7 @@ For details of changes by release see the [change log](https://github.com/App-vN * [@reisenberger](https://github.com/reisenberger) - Add new .HandleInner(...) syntax for handling inner exceptions natively. * [@rjongeneelen](https://github.com/rjongeneelen) and [@reisenberger](https://github.com/reisenberger) - Allow PolicyWrap configuration to configure policies via interfaces. * [@reisenberger](https://github.com/reisenberger) - Performance improvements. +* [@awarrenlove](https://github.com/awarrenlove) - Add ability to calculate cache Ttl based on item to cache. # Sample Projects diff --git a/src/Polly.Net40Async.nuspec b/src/Polly.Net40Async.nuspec index 2394b5e767..5202b3793a 100644 --- a/src/Polly.Net40Async.nuspec +++ b/src/Polly.Net40Async.nuspec @@ -18,6 +18,7 @@ 5.7.0 --------------------- - Minor cache fixes + - Add ability to calculate cache Ttl based on item to cache 5.6.1 --------------------- diff --git a/src/Polly.nuspec b/src/Polly.nuspec index e36afcafa4..9d41450437 100644 --- a/src/Polly.nuspec +++ b/src/Polly.nuspec @@ -18,6 +18,7 @@ 5.7.0 --------------------- - Minor cache fixes + - Add ability to calculate cache Ttl based on item to cache 5.6.1 ---------------------