I have implemented Polly in it's own "retry" HttpClient DelegateHandler
in a dll written to .NET Standard 2.0. I have the Polly v7.2.3 package. My HttpClient
is running separate from an HttpClientFactory
since only one instance will ever exist during the short lifetime of the dll.
My problem is this: The code executes great when my internet is working. However, when I disconnect my internet it throws a TaskCanceledException
on the first retry and does not retry any more. Here are the relevant parts of my code...
inside the ctor of my typed HttpClient:
this.Client = new System.Net.Http.HttpClient(
new ATCacheDelegatingHandler(
new RetryPolicyDelegatingHandler(
new HttpClientHandler()))));
inside my Retry delegating handler:
this.RetryPolicy =
Policy.Handle<HttpRequestException>()
.Or<TaskCanceledException>()
.WaitAndRetryAsync(numRetries,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt-1) * 15));
So I did my research here on SO and found this very promising explanation and solution that suggested I call Dispose
on the result. HttpClient Polly WaitAndRetry policy
Here is my updated code using that solution. The call to WaitAndRetryAsync
complains it is unable to resolve the OnRetry
method because it is looking for an 'Action<Exception, TimeSpan>'
private void WaitAndRetry(int numRetries)
{
this.RetryPolicy =
Policy.Handle<HttpRequestException>()
.Or<TaskCanceledException>()
.WaitAndRetryAsync(numRetries,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt-1) * 15)
, OnRetry); // reference to the method below
}
// unable to match to these parameters from the "WaitAndRetryAsync" call above
private Task OnRetry(DelegateResult<HttpResponseMessage> response, TimeSpan span, int retryCount, Context context)
{
if (response == null)
return Task.CompletedTask;
// this is the "Dispose" call from that SO solution I referenced above
response.Result?.Dispose();
return Task.CompletedTask;
}
Unfortunately there is NO support for a DelegateResult<HttpResponseMessage>
parameter in the version of Polly I am using. All onRetry
support expects the first parameter to be an "Exception". I am dead in the water using the Dispose
solution if I can't access the disposable object.
Update: I want to be able to call Dispose()
to affect the fix from the other StackOverflow feedback. But I can't because the onRetry
method does not support the same set of parameters (i.e., the "response" object). It looks like the Polly API has changed. If so, what is the new way to gain access to the response so I can Dispose
of it? Either that or is there another way to resolve the error I am getting?
So I am stuck trying to get this solution working or finding another way to resolve this exception. I welcome any feedback on how to specify the object to Dispose. Alternative approaches are also welcome.
All you need to do is to specify the HttpResponseMessage
as a return type when you declare your policy.
IAsyncPolicy<HttpResponseMessage> retryPolicy = Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.Or<TaskCanceledException>()
.WaitAndRetryAsync(numRetries,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1) * 15),
OnRetry);
So, instead of Policy.Handle...
use Policy<HttpResponseMessage>.Handle...