Polly a .NET fault-handling wrapper that allows developers to express policies in thread safe manner.
Policies could be made over:
More: <https://github.com/App-vNext/Polly>
Simple Demo:
We can also create multiple policy to handle multiple faults, like server is down and we are unable to establish connection with the service. In that case at initial call above code will produce exception. So, I made some changes in code, created two policies and wrapped first one with 2nd once.
Now you can see variation in fault message
In case of DotNetCore we can use Microsoft.Extensions.Http.Polly, with given example.
Policies could be made over:
- Retry
- Circuit Breaker
- Timeout
- Bulkhead Isolation
- Fallback.
More: <https://github.com/App-vNext/Polly>
Simple Demo:
using Polly; using System; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; namespace PollyRetry { class Program { static void Main(string[] args) { HttpRequestDemo(); Console.WriteLine("Done!"); Console.ReadLine(); } private static void HttpRequestDemo() { HttpStatusCode[] httpStatusCodesWorthRetrying = { HttpStatusCode.RequestTimeout, // 408 HttpStatusCode.InternalServerError, // 500 HttpStatusCode.BadGateway, // 502 HttpStatusCode.ServiceUnavailable, // 503 HttpStatusCode.GatewayTimeout, // 504 HttpStatusCode.NotFound // 404 }; var httpRetryPolicy = Policy.HandleResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode)) .OrResult(r => r.StatusCode == HttpStatusCode.BadGateway) .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { Console.WriteLine($"Unable to complete operation after {time.TotalSeconds:n1}s ({ex.Result.StatusCode})"); }); using (var client = new HttpClient()) { client.BaseAddress = new Uri("http://localhost:51976/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = httpRetryPolicy.ExecuteAndCapture(() => { return client.GetAsync("api/order").Result; }).FinalHandledResult; if (response != null && response.IsSuccessStatusCode) { Console.WriteLine("Got valid response from API"); } } } } }
We can also create multiple policy to handle multiple faults, like server is down and we are unable to establish connection with the service. In that case at initial call above code will produce exception. So, I made some changes in code, created two policies and wrapped first one with 2nd once.
using Polly; using System; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; namespace PollyRetry { class Program { static async System.Threading.Tasks.Task Main(string[] args) { await HttpRequestDemoAsync(); Console.WriteLine("Done!"); Console.ReadLine(); } private static async System.Threading.Tasks.Task HttpRequestDemoAsync() { int retryCount = 5; HttpStatusCode[] httpStatusCodesWorthRetrying = { HttpStatusCode.RequestTimeout, // 408 HttpStatusCode.InternalServerError, // 500 HttpStatusCode.BadGateway, // 502 HttpStatusCode.ServiceUnavailable, // 503 HttpStatusCode.GatewayTimeout, // 504 HttpStatusCode.NotFound // 404 }; var httpRetryPolicy = Policy.HandleResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode)) .OrResult(r => r.StatusCode == HttpStatusCode.BadGateway) .WaitAndRetryAsync(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, calculatedWaitDuration) => { Console.WriteLine($"Unable to complete operation after {calculatedWaitDuration.TotalSeconds:n1}s ({exception.Result.StatusCode})"); }); var exceptionPolicy = Policy .Handle<Exception>() .WaitAndRetryAsync(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, calculatedWaitDuration) => { Console.WriteLine($"Error while performing operation after {calculatedWaitDuration.TotalSeconds:n1}s {exception.Message}"); }) .WrapAsync(httpRetryPolicy); using (var client = new HttpClient()) { client.BaseAddress = new Uri("http://localhost:51976/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = (await exceptionPolicy.ExecuteAndCaptureAsync(() => { return client.GetAsync("api/order"); })).FinalHandledResult; if (response != null && response.IsSuccessStatusCode) { Console.WriteLine("Got valid response from API"); } } } } }
Now you can see variation in fault message
In case of DotNetCore we can use Microsoft.Extensions.Http.Polly, with given example.