Reputation: 15817
I am trying to get started with Polly. Please see my Startup class below:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services//.AddCustomMvc(Configuration)
//.AddCustomAuthentication(Configuration)
.AddHttpServices()
.AddHttpClientServices(Configuration)
.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//This is not changed.
}
}
static class ServiceCollectionExtensions
{
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddTransient<HttpClientRequestIdDelegatingHandler>();
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5));
services.AddHttpClient<IValuesService, ValuesService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
return services;
}
public static IServiceCollection AddHttpServices(this IServiceCollection services)
{
services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddHttpClient<IValuesService, ValuesService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
return services;
}
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
}
I am using the HttpClient
like this:
public class ValuesService : IValuesService
{
private readonly HttpClient _apiClient;
public ValuesService(HttpClient httpClient)
{
_apiClient = httpClient;
}
public async Task<string> GetValue()
{
var uri = API.Values.GetValues("http://localhost:55461/api");
//The line below throws a SocketException
var responseString = await _apiClient.GetStringAsync(uri);
return responseString;
}
}
GetValue()
attempts to access the Web API once and then fails. Why does it not attempt to access the Web API multiple times as configured?
Upvotes: 0
Views: 2267
Reputation: 8156
The policy specification
HttpPolicyExtensions.HandleTransientHttpError()
handles the faults:
HttpRequestException
Reference: Polly wiki on Polly-and-HttpClientFactory
This mirrors the faults handled by the default HttpClientFactory implementation .AddTransientHttpErrorPolicy(...)
extension method.
To handle SocketException
additionally, you can extend the policies similarly to the example in the Polly-HttpClientFactory documentation. For example:
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.Or<SocketException>()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.Or<SocketException>()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
(Based on comments to the original question about SocketException
being raised and retries not occurring, this answer explains how to make the policies handle SocketException
.)
Upvotes: 1