I'm trying to use Polly on an HttpClient with three policies: Retry, CircuitBreaker, Timeout. The result I would like to achieve is that the CircuitBreaker always starts counting from the last error of the Retry and not from all errors. For example, let's say I have a retry count of 3, I would like behavior like this:
Retry 1 -> HttpRequestException
Retry 2 -> HttpRequestException
Retry 3 -> HttpRequestException
CircuitBreaker Exception count 1
Retry 1 -> HttpRequestException
Retry 2 -> HttpRequestException
Retry 3 -> HttpRequestException
CircuitBreaker Exception count 2
...
This is the class that contains the 3 policies:
public class PollyPoliciesService : IPollyPolicyService, IPollyPolicyConsentsService
{
private readonly ILogger<PollyPoliciesService> _logger;
private readonly IDistributedCache _cache;
private readonly PollySettings _pollySettings;
public AsyncCircuitBreakerPolicy<HttpResponseMessage> HttpConsentCircuitBreakerPolicy { get; private set; }
public AsyncRetryPolicy<HttpResponseMessage> HttpConsentsWaitAndLongRetryPolicy { get; private set; }
public AsyncTimeoutPolicy<HttpResponseMessage> HttpTimeoutPolicy { get; private set; }
public AsyncRetryPolicy<HttpResponseMessage> HttpRetryPolicy { get; private set; }
public PollyPoliciesService(ILogger<PollyPoliciesService> logger, IDistributedCache cache,
IOptions<PollySettings> pollyOptions)
{
Guard.Against.Null(logger);
Guard.Against.Null(cache);
Guard.Against.Null(pollyOptions);
_logger = logger;
_cache = cache;
_pollySettings = pollyOptions.Value;
InitializeProperty();
}
private void InitializeProperty()
{
HttpConsentCircuitBreakerPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>()
.CircuitBreakerAsync(3,TimeSpan.FromSeconds(30), OnBreak, OnReset);
HttpTimeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(_pollySettings.HttpTimeoutInSeconds);
HttpRetryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.RetryAsync(_pollySettings.HttpRetryNumber);
HttpConsentsWaitAndLongRetryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
private void OnBreak(DelegateResult<HttpResponseMessage> result, TimeSpan timeSpan)
{
_logger.LogWarning("CircuitBreaker is open");
}
private void OnReset()
{
_logger.LogInformation("CircuitBreaker is restored");
}
}
And this is how I combined the policies::
Policy.WrapAsync(policyService.HttpRetryPolicy,policyConsentsService.HttpConsentCircuitBreakerPolicy,policyService.HttpTimeoutPolicy);
Unfortunately what I get is that after the third exception raised by the Retry the CircuitBreaker is triggered. How can I solve the problem?
Thanks