Search code examples
.net-corestartupdotnet-httpclientpollycircuit-breaker

Polly Circuit breaker not maintaining state with .net core HTTP Client


I have implemented the polly retry and Circuit breaker policy (wrapped). when the call fails and the circuit is open for the previous call the next call again goes to the retry and hit the circuit breaker again instead of just throwing the circuitbreakexception. I think somehow the HTTP client is getting recreated again even though am using the typed client. I am not able to figure the issue. Here is the code

Startup

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddHttpClient<IIntCall, IntCall>().WrapResilientPolicies();
    }

Interface

public interface IIntCall
    {
        Task<bool> DoSomething();
    }

Implementation:

public class IntCall : IIntCall
    {
    private readonly HttpClient client;

    public IntCall(HttpClient httpClient)
    {
        this.client = httpClient;
    }

    public async Task<bool> DoSomething()
    {
        var response = await client.GetAsync("http://www.onegoogle.com");
        var content = await response.Content.ReadAsStringAsync();
        return false;
    }
}

Polly Implementation

public static class CBExtensions
    {
        public static void WrapResilientPolicies(this IHttpClientBuilder builder)
        {
            builder.AddPolicyHandler((service, request) =>
            GetRetryPolicy().WrapAsync(GetCircuitBreakerPolicy()));
        }

    private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
    {
        return HttpPolicyExtensions.HandleTransientHttpError()
            .CircuitBreakerAsync(3, TimeSpan.FromSeconds(30), (result, retryAttempt) =>
            {
                Debug.WriteLine("circuit broken");
            },
            () =>
            {
                Debug.WriteLine("circuit closed");
            });
    }

    private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions.HandleTransientHttpError()
            .Or<Exception>(e => !(e is BrokenCircuitException))
          .WaitAndRetryAsync(3,
              retryAttempt => TimeSpan.FromMilliseconds(500),
              onRetry: (context, attempt) =>
              {
                  Debug.WriteLine("error");
              }
          );
    }
}

Solution

  • I figured the issue. because I am fetching the request details the policy is injected every call and hence the state is renewed. I moved my code from

    public static void WrapResilientPolicies(this IHttpClientBuilder builder)
            {
                builder.AddPolicyHandler((service, request) =>
                GetRetryPolicy().WrapAsync(GetCircuitBreakerPolicy()));
            }
    

    to this

    public static void WrapResilientPolicies(this IHttpClientBuilder builder)
            {
                builder.AddPolicyHandler(
                    GetRetryPolicy().WrapAsync(GetCircuitBreakerPolicy()));
            }