question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Polly Timeout: How to utilize optimistic timeout on all HttpClient.GetAsync calls when using HttpClientFactory

See original GitHub issue

Summary: What are you wanting to achieve?

This is somewhat related to #907, but within the context of HttpClientFactory. If a CancellationToken is required to be passed to the HttpClient instance for optimistic timeout, how would you go about doing that when nearly everything about the policy setup with HttpClientFactory is implicit? There is no CancellationToken object in sight to reference or pass around!

What code or approach do you have so far?

I have two separate source files here: the main program where all the DI-framework magic with HttpClientFactory happens, and the GitHubService class that actually makes the HTTP calls.

In Program.cs:

var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();
var jitterDelay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromSeconds(1), 6);
var retryPolicy = Policy
    .Handle<RateLimitRejectedException>()
    .OrTransientHttpError()
    .WaitAndRetryAsync(jitterDelay);
var timeoutPolicy = Policy
    .TimeoutAsync<HttpResponseMessage>(10);
var host = new HostBuilder()
    .ConfigureServices(services =>
    {
        services.AddHttpClient<IGitHubService, GitHubService>((sp, client) =>
        {
            client.BaseAddress = new Uri("https://api.github.com");
            client.DefaultRequestHeaders.Add(
                HeaderNames.Accept, "application/vnd.github.v3+json");
            client.DefaultRequestHeaders.Add(
                HeaderNames.UserAgent, "HttpRequestsSample");
            client.Timeout = TimeSpan.FromSeconds(60); // overall timeout
            // pass config file as second argument in GitHubService constructor
            ActivatorUtilities.CreateInstance<GitHubService>(sp, client, config);
        })
        .AddPolicyHandler(retryPolicy);
        .AddPolicyHandler(timeoutPolicy);
    })
    .Build();
var gitHubService = host.Services.GetRequiredService<GitHubService>();
var gitHubZen = await gitHubService.GetZenAsync();
Console.WriteLine(gitHubZen);

In GitHubService.cs:

public class GitHubService : IGitHubService
{
    private readonly HttpClient _httpClient;
    // other private fields to populate via config

    public GitHubService(HttpClient httpClient, IConfiguration config)
    {
        _httpClient = httpClient;
        // populate private fields via config
    }

    public async Task<string> GetZenAsync()
    {
        using var response = await _httpClient.GetAsync("/zen");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

public interface IGitHubService
{
}

Even if I modified GetAsync() to include a CancellationToken, where would it come from? Should it be included in the constructor for GitHubService?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
fsgarin-lacitycommented, Feb 14, 2022

Regarding documentation, we have #853 to update any out-of-date documentation, but the HttpClientFactory integration is a bit of a grey area as the implementation is actually in the ASP.NET Core repo, and there’s further documentation of their own here and here.

Oof, so that explains why a lot of the documentation regarding HttpClientFactory keeps squawking about crap I don’t care about such as PageModel. My use case is simply just a console app that gets scheduled to run at specific times via Task Manager in Windows Server and needs to communicate to API endpoints via HTTP. I also like the idea of having a well-behaved client app that talks to API endpoints, which is how I stumbled upon Polly and HttpClientFactory, which solves the exhausted socket and stale DNS issues.

Anyway, I didn’t realize until you told me that CancellationTokenSource.Token exists. I might just use that for per-call timeouts instead while leaving the other policies in place. I have another use case where the overall timeout in HttpClient is set to 5 minutes and the per-call timeout has to be 1 minute, so I’m guessing that will change the calculus a bit when deciding between pessimistic vs. optimistic.

Thanks for the discussion. As I continue to work through this console app, I’ll make note on which parts of the documentation aren’t clear and give feedback (if any) to #853.

0reactions
martincostellocommented, Feb 14, 2022

I’ll make note on which parts of the documentation aren’t clear and give feedback (if any) to https://github.com/App-vNext/Polly/issues/853.

Great, thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Polly Timeout optimistic using HttpClientFactory. How can I ...
You should chain the retry and timeout policy into a combined policy. You have two options: Wrap method .AddPolicyHandler(retryPolicy.
Read more >
HttpClient retry on HTTP timeout with Polly and ...
This handler will throw a TimeoutRejectedException when the url called have been unresponsive for 5 seconds. STEP 3: USE THE IHttpClientFactory ...
Read more >
Polly 7.2.4
Optimistic timeout operates via CancellationToken and assumes delegates you execute support co-operative cancellation. You must use Execute/Async(...) overloads ...
Read more >
Using the Polly Timeout when making a Http Request
I define two policies, the first is a simple Retry Policy that is set to retry three times. The other is a Timeout...
Read more >
Polly Timeout optimistic using HttpClientFactory. How can I ...
You should chain the retry and timeout policy into a combined policy. You have two options: Wrap method .AddPolicyHandler(retryPolicy.Wrap(timeoutPolicy)).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found