I'm at a loss with using the cache policy from the Polly project. I've set up all according to the examples, and it basically seems to work.
I've written a unit test, where the value is successfully retrieved, put to the cache and read from the cache on later invocations. However, when I run the code in the asp.net core context, it's not working as expected. The wrapped action is executed and the value is retrieved. However, the put to cache method is never executed. I tried to use my own IAsyncCacheProvider, to debug the issue. And its PutAsync method is never called in the asp.net context. It is called though, when running in a unit test.
Here my service configuration
services.AddSingleton<IAsyncCacheProvider, MemoryCacheProvider>();
services.AddSingleton<IPolicyRegistry<string>, PolicyRegistry>();
And here excerpts from the class causing the issues.
public Bar(
IPolicyRegistry<string> policyRegistry,
IService service,
IAsyncCacheProvider cacheProvider)
{
this.policyRegistry = policyRegistry;
this.service = service;
this.cacheProvider = cacheProvider;
}
public Task<bool> Foo(Guid id)
{
var cachePolicy = this.GetPolicy();
return cachePolicy.ExecuteAsync(
_ => this.service.Foo(id),
new Context("policyKey" + id));
}
private CachePolicy<bool> GetPolicy()
{
if(!this.policyRegistry.TryGet(PolicyKey, out CachePolicy<bool> policy))
{
policy = Policy.CacheAsync<bool>(
this.cacheProvider.AsyncFor<bool>(),
TimeSpan.FromMinutes(5),
(c, s) => { },
(c, s) => { },
(c, s) => { },
(c, s, e) => { },
(c, s, e) => { });
this.policyRegistry.Add(PolicyKey, policy);
}
return policy;
}
Any ideas, what could cause this behavior? When I put breakpoints, then it never tries to add the return value to the cache. There isn't any exception either.
I think I found the answer in the source code.
In the class CacheEngine there is the following code.
if (ttl.Timespan > TimeSpan.Zero && result != null && !result.Equals(default(TResult)))
{
try
{
await cacheProvider.PutAsync(cacheKey, result, ttl, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
onCachePut(context, cacheKey);
}
catch (Exception ex)
{
onCachePutError(context, cacheKey, ex);
}
}
So whenever the return value of this service, which is bool, happens to be false, it is not put to the cache because that is actually the default value of the type. In the unit test I happened to use true as the returned value, therefore the cache worked.