Polly icon indicating copy to clipboard operation
Polly copied to clipboard

How do I Cancel HttpClient.SendAsync on Timeout when Using the HttpClientFactory extensions

Open SOFSPEEL opened this issue 3 years ago • 0 comments

Summary: What are you wanting to achieve?


I have a policy setup to retry 5 times after a individual timeout. I'd like to cancel the httpclient.SendAsync() after each timeout, and I know how to set this up if I wasn't using HttpClientFactory extensions, like so:
Policy timeoutPolicy = Policy.TimeoutAsync(30, TimeoutStrategy.Optimistic);
HttpResponseMessage httpResponse = await timeoutPolicy
    .ExecuteAsync(
        async ct => await httpClient.GetAsync(requestEndpoint, ct), // Execute a delegate which responds to a CancellationToken input parameter.
        CancellationToken.None // CancellationToken.None here indicates you have no independent cancellation control you wish to add to the cancellation provided by TimeoutPolicy.
    );

So problem is that I am using HttpClientFactory extensions where I've setup my policies as follows:

   services
                .AddHttpClient<MyHttpClient>()
                .AddPolicyHandler(FallbackPolicyExceptionOrForbiddenStatus)
                .AddPolicyHandler(GetCircuitBreakerPolicy())
                .AddPolicyHandler(GetRetryPolicy())
                .AddPolicyHandler((provider, message) => Policy.TimeoutAsync<HttpResponseMessage>(10)); 

And these policies work as expected, note that I used Optimistic timeout (i.e. the default) except for the fact that I don't think my MyHttpClient.SendAsync calls are being cancelled after an individual timeout.

More to the point is the following:

  • The above code puts MyHttpClient in the my autofac container.
  • Then MyHttpClient is made available in MyController(MyHttpClient myHttpClient) thru autofac constructor injection
  • Then I use myHttpClient in the controller as follows:
var response = await myHttpClient.SendAsync(CreateRequest(rootUrl, HttpMethod.Get)).ConfigureAwait(false);

Now I understand that adding a cancellation token to the above .SendAsync won't help, since it's the token generated by the optimistic TimeoutPolicy token that actually gets cancelled on timeout.

So ultimately the question is how do I get the myHttpClient.SendAsync to latch onto the cancellation token that the TimeoutPolicy generates?


SOFSPEEL avatar Sep 27 '20 16:09 SOFSPEEL