I'm just trying out the Polly CircuitBreakerAsync and it's not working as I expect.
What am I doing wrong here? I expect the code below to complete and say the circuit is still closed.
using Polly;
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
var circuitBreaker = Policy
.Handle<Exception>()
.CircuitBreakerAsync(
3, // ConsecutiveExceptionsAllowedBeforeBreaking,
TimeSpan.FromSeconds(5) // DurationOfBreak
);
Console.WriteLine("Circuit state before execution: " + circuitBreaker.CircuitState);
await circuitBreaker.ExecuteAsync(() => Task.Delay(25));
await circuitBreaker.ExecuteAsync(() => Task.Delay(25));
await circuitBreaker.ExecuteAsync(() => { throw new System.Exception(); });
await circuitBreaker.ExecuteAsync(() => Task.Delay(25));
await circuitBreaker.ExecuteAsync(() => Task.Delay(25));
Console.WriteLine("Circuit state after execution: " + circuitBreaker.CircuitState);
}
}
Fiddle: https://dotnetfiddle.net/unfKsC
Output:
Circuit state before execution: Closed
Run-time exception (line 25): Exception of type 'System.Exception' was thrown.
Stack Trace:
[System.Exception: Exception of type 'System.Exception' was thrown.]
at Program.<MainAsync>b__2() :line 25
at Polly.Policy.<>c__DisplayClass116_0.<ExecuteAsync>b__0(Context ctx, CancellationToken ct)
at Polly.CircuitBreakerSyntaxAsync.<>c__DisplayClass4_1.<<CircuitBreakerAsync>b__2>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Polly.CircuitBreaker.CircuitBreakerEngine.<ImplementationAsync>d__1`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Polly.Policy.<ExecuteAsync>d__135.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Program.<MainAsync>d__a.MoveNext() :line 25
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Program.Main(String[] args) :line 9
This is working as expected
https://github.com/App-vNext/Polly/wiki/Circuit-Breaker
Exception handling
A circuit-breaker exists as a measuring-and-breaking device: to measure handled exceptions thrown by actions you place through it, and to break when the configured failure threshold is exceeded.
- A circuit-breaker does not orchestrate retries.
- A circuit-breaker does not (unlike retry) absorb exceptions. All exceptions thrown by actions executed through the policy (both exceptions handled by the policy and not) are intentionally rethrown. Exceptions handled by the policy update metrics governing circuit state; exceptions not handled by the policy do not.
In short it doesn't handle your exceptions, it rethrows them