Is Polly able to cache selectively based off of parameters like response code, response headers, etc
I could not find any documentation on what types of responses Polly decides to cache, or whether it's possible to cache selectively based on attributes like the response code. Right now a workaround I've tried is using ResultTtl to vary the ttl based on response code, and setting a very short ttl for non 200 responses.
Is there any good way to have the cache policy ignore all responses that are not 200?
@citrus7 Great question. ( /cc @stevejgordon, I think you also suggested/asked something similar once)
You can make Polly not cache a returned result by configuring CachePolicy with a ResultTtl (a strategy which determines the ttl to apply based on the result returned), such that it returns TimeSpan.Zero ttl for items you don't want to cache:
Func<Context, HttpResponseMessage, Ttl> cacheOnly200OKfilter =
(context, result) => new Ttl(
timeSpan: result.StatusCode == HttpStatusCode.OK ? TimeSpan.FromMinutes(5) : TimeSpan.Zero,
slidingExpiration: /* whether you want sliding expiration for the cached cases */
);
IAsyncPolicy<HttpResponseMessage> cacheOnly200OKpolicy =
Policy.CacheAsync<HttpResponseMessage>(
cacheProvider: /* whatever cache provider you are using */,
ttlStrategy: new ResultTtl(cacheOnly200OKfilter),
onCacheError: /* whatever cache error logging */
); // or whatever richer CacheAsync overload taking an ITtlStrategy ttlStrategy
When the ITtlStrategy returns TimeSpan.Zero as the ttl, the policy intentionally doesn't even attempt to put the item to the cache. In other words, this is certain (not just lucky due to timing) to prevent such items being cached.
EDITED: for syntax
For future ref: It would be easily also to handle selective caching natively within Polly: this example commit shows a pattern (only applied to the async implementation and a single new overload). However, we would need carefully to consider how many policy configuration overloads should be added: current policy configuration syntax promotes a proliferation of overloads.
For now, documented the above ResultTtl : ITtlStrategy approach, which works well.
As ResultTtl<TResult> : ITtlStrategy<TResult> and ITtlStrategy<TResult> does not extend ITtlStrategy it may be worth to point out that the cache provider need to implement IAsyncCacheProvider<TResult>, i.e it is incompatible with for example the MemoryCacheProvider.
@lindstromhenrik You can convert MemoryCacheProvider to a version generic in TResult using
myMemoryCacheProvider.AsyncFor<TResult>
// or (for sync usage)
myMemoryCacheProvider.For<TResult>
as described in the MemoryCacheProvider documentation.
Thanks, sorry I missed that.
_Triage of issues:_ As previously mentioned, at present we do not want to add further policy configuration overloads, as the plan is to simplify these for Polly v8. However, this feature will be easy to implement - and is planned to be added - once the new syntax is in place.
Most helpful comment
@lindstromhenrik You can convert
MemoryCacheProviderto a version generic inTResultusingas described in the MemoryCacheProvider documentation.