Polly framework CircuitBreakerAsync does not retry if exception occur

Demon Hunter picture Demon Hunter · Apr 4, 2016 · Viewed 9.9k times · Source

I am using Polly framework for transient fault handling. For synchronous operations Polly circuit breaker policy works fine but when I created its async version it does not retries the execution. Kindly suggest :

Asynchronous method:

private async static Task HelloWorld()
    {
        if (DateTime.Now < programStartTime.AddSeconds(10))
        {
            Console.WriteLine("Task Failed.");
            throw new TimeoutException();
        }
        await Task.Delay(TimeSpan.FromSeconds(1));
        Console.WriteLine("Task Completed.");
    }

Polly circuit breaker async policy:

private static void AsyncDemo3(Func<Task> action)
    {
        programStartTime = DateTime.Now;

        Policy policy = Policy
            .Handle<TimeoutException>()
            .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));
        try
        {
            var a = policy.ExecuteAndCaptureAsync(action, true).GetAwaiter().GetResult();
        }
        catch (AggregateException ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
    }

Executing the Polly circuit breaker policy :

AsyncDemo3(HelloWorld);

Kindly help the find and resolve the problem.

Answer

svick picture svick · Apr 4, 2016

I believe you misunderstood what the circuit breaker policy does.

What it does is that if you call it the given number of times and it fails each time, then it will stop calling the given method for a certain amount of time. But it does not retry by itself.

So to do what I think you want to do, you need to combine retry policy with circuit breaker policy. One way to do that would be:

Policy retryPolicy = Policy.Handle<TimeoutException>().RetryAsync(3);

Policy circuitBreakerPolicy = Policy
    .Handle<TimeoutException>()
    .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));

try
{
    retryPolicy.ExecuteAsync(() => circuitBreakerPolicy.ExecuteAsync(action, true))
        .GetAwaiter().GetResult();
}
…

The output of this code is:

Task Failed.
Task Failed.
Task Failed.
Exception: The circuit is now open and is not allowing calls.