2

Is there an elegant way to do it? I have too many request being passed in a specific time that throwing a 503 (service unavailable) exception. Thanks

    protected void CallApi(string uriString)
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(_apiUrl);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            var response = client.PostAsync(uriString, new StringContent("{ Data to be posted }")).Result;

            for (int i = 0; i < MaxRetries; i++)
            {
                if (response.IsSuccessStatusCode)
                {
                    break;
                }
                else
                {
                    Thread.Sleep(TimeSpan.FromMinutes(1));
                    response = client.PostAsync(uriString, new StringContent("{ Data to be posted }")).Result;
                }
            }
            throw new Exception("status : " + (int)response.StatusCode + ", Content :" + response.Content.ReadAsStringAsync().Result);
        }
    }
Dev
  • 171
  • 2
  • 18
  • Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Polly targets .NET Standard 1.1 and .NET Standard 2.0. http://www.thepollyproject.org . https://github.com/App-vNext/Polly/wiki/ . – jazb Oct 15 '18 at 01:06
  • 1
    Possible duplicate of [Retrying HttpClient Unsuccessful Requests](https://stackoverflow.com/questions/19260060/retrying-httpclient-unsuccessful-requests) – ProgrammingLlama Oct 15 '18 at 01:06
  • Also, I recommend reading [this](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/) to find out why constantly creating new instances of `HttpClient` is a bad idea. It ended up causing timeouts connecting to our database because doing so had used up all of the available sockets on the machine. – ProgrammingLlama Oct 15 '18 at 01:08
  • 1
    Microsoft docs [here](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.7.2#remarks) state that "HttpClient is intended to be instantiated once and re-used throughout the life of an application.", but note that things like `DefaultRequestHeaders` are not thread safe (but you can craft a request manually and add the headers to the request, for example). – ProgrammingLlama Oct 15 '18 at 01:10
  • 2
    If you get a 503 error you might consider checking the [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header before flooding the service with even more requests due to a blind retry mechanism. – John Wu Oct 15 '18 at 05:22
  • I try to use retry-after but not sure how it works. thanks – Dev Oct 15 '18 at 05:25

1 Answers1

8

Polly Example:

var httpClient = new HttpClient();
var maxRetryAttempts = 3;
var pauseBetweenFailures = TimeSpan.FromSeconds(2);

var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetryAsync(maxRetryAttempts, i => pauseBetweenFailures);

await retryPolicy.ExecuteAsync(async () =>
{
    var response = await httpClient
      .DeleteAsync("https://example.com/api/products/1");
    response.EnsureSuccessStatusCode();
});
jazb
  • 5,498
  • 6
  • 37
  • 44
  • I tried this solution with httpClient.PostAsync, calling to wrong url which returns 404 but it doesn't wait for 3 retries. Could anyone help? – Edo Jul 23 '20 at 10:47