I am implementing the Circuit Breaker and Retry patterns via Polly in .NET framework 4.5.2.
I wish to see if my understanding is correct.
Question 1: If there is a network outage and the circuit breaker has reached the exceptionsAllowedBeforeBreaking number, gone into the open state and waited for the durationOfBreak period, the circuit will be open for new requests but those that have been sent will throw an exception?
Question 2: If the desired behavior is for those requests that had exceptions to be retried instead of the circuit breaker throwing an exception then the Retry policy needs to be implemented in addition to the Circuit Breaker policy. My understanding of this is that the behavior in question 1 would occur, and then the retry would be attempted.
A. If there is a network outage or the service is down and the desired behavior is for a request to be retried as soon as the network is restored or the service is up again, a RetryForever would need to be performed. Is there a better way of doing this? Effectively there would be lots of blocking, correct?
In terms of code, my policies are currently defined as:
const int maxRetryAttempts = 3;
const int exceptionsAllowedBeforeBreaking = 2;
const int pauseBetweenFailures = 2;
readonly Policy retryPolicy = Policy
.Handle<Exception>()
.RetryAsync(maxRetryAttempts, (exception, retryCount) => System.Diagnostics.Debug.WriteLine($"Retry {retryCount}"));
readonly Policy circuitBreakerPolicy = Policy
.Handle<Exception>()
.CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,
durationOfBreak: TimeSpan.FromSeconds(pauseBetweenFailures),
onBreak: (e, span) => System.Diagnostics.Debug.WriteLine("Breaking circuit for " + span.TotalMilliseconds + "ms due to " + e.Message),
onReset: () => System.Diagnostics.Debug.WriteLine("Trial call succeeded: circuit closing again."),
onHalfOpen: () => System.Diagnostics.Debug.WriteLine("Circuit break time elapsed. Circuit now half open: permitting a trial call."));
My calling code is done as:
var response = await retryPolicy.WrapAsync(circuitBreakerPolicy).ExecuteAsync(() => this.client.SendAsync<TData, JObject>(message, cancel, jsonSerializer));
I have observed that if I disconnect the network past the amount of time necessary to run all retries on the circuit breaker, the CancellationToken is set to cancel and all requests fail at that point. If the network is restored before that happens, then the requests are retried.