PROPOSAL: Cache policy
See original GitHub issueProposal: Cache policy
Purpose
To provide the ability to serve results from a cache, instead of executing the governed func.
Scope
- A non-exception handling policy.
- All sync and async variants
- Only result-returning (
Func<TResult>
), not void (Action
) executions.
Configuration
The cache item expiry duration would be configured on the CachePolicy
at configuration time, not passed at execution time:
- This keeps
CachePolicy
in line with the Polly model, where the behavioural characteristics of policies are defined at configuration time, not call time. This makes for a cache policy with given behaviour which can be shared across calls. - Adding bespoke
.Execute()
overloads onCachePolicy
would present problems for the integration ofCachePolicy
intoPolicyWrap
. (ThePolicyWrap
(was Pipeline) feature in its proposed from requires that all policies have common.Execute()
etc overloads.)
Configuration syntax
For Policy<TResult> - default cache
CachePolicy<TResult> cachePolicy = Policy
.Cache<TResult>(TimeSpan slidingExpirationTimespan);
For Policy<TResult> - advanced cache
Users may want more control over caching characteristics or to use an alternative cache provider (Http cache or third-party). The following overload is also proposed:
CachePolicy<TResult> cachePolicy = Policy
.Cache<TResult>(IResultCacheProvider<TResult> cacheProvider);
where:
// namespace Polly.Cache
interface IResultCacheProvider<TResult>
{
TResult Get(Context);
void Put(Context, TResult);
}
- The
Context
itself is not the key; it is an execution context that travels with each Execute invocation on a Polly policy. Implementations should derive a cache key to use from elements in theContext
. The usual cache key would beContext.ExecutionKey
. See #139 - Basing the
IResultCacheProvider
Get/Put signatures aroundContext
rather than astring cacheKey
allows implementers power to develop a more complex caching strategy around other keys or user information on theContext
.
Example execution syntax
// TResult form
TResult result = cachePolicy
.Execute(Func<TResult> executionFunc, new Context(executionKey)); // The executionKey is the cacheKey. See keys proposal.
(and other similar existing overloads taking a Context
parameter)
Default implementation
The proposed implementation for the simple cache configuration overload is to use System.Runtime.Memory.MemoryCache.Default
and the configured Timespan slidingExpirationTimespan
to create a Polly.Cache.MemoryCacheProvider<TResult> : Polly.Cache.IResultCacheProvider<TResult>
.
Operation
- Checks the cache for a value stored under the cache key; returns it if so.
- Throws an
InvalidCastException
if the value in the cache cannot be cast toTResult
- Throws an
- Invokes
executionFunc
if (and only if) a value could not be returned from cache. - Before returning a result from a non-faulting invoking
executionFunc
, caches it under the given cache key for the given timespan.
Comments?
Comments? Alternative suggestions? Extra considerations to bear in mind?
Have scenarios to share where you’d use this? (could inform development)
Issue Analytics
- State:
- Created 7 years ago
- Comments:76 (66 by maintainers)
Top GitHub Comments
Closing via #332
CachePolicy
has been merged into themaster
branch, for release shortly as part of Polly v5.4.0.The first cache provider implementation to go with
CachePolicy
- based around .NET’s in-builtMemoryCache
- is available at: https://github.com/App-vNext/Polly.Caching.MemoryCache.The two will be released together to nuget, as soon as we hook up the build and nuget feed onto https://github.com/App-vNext/Polly.Caching.MemoryCache. /cc @joelhulen
Doco at: https://github.com/App-vNext/Polly/wiki/Cache
@perfectsquirclehttps://github.com/perfectsquircle I’m also like @reisenberger happy to help, although my time is limited currently.
If you are more interested in local caches I’m happy to write the cloud-based ones. Let us know how you wish to help and we’ll give you any support that is needed.