Ejemplo n.º 1
0
        public void Should_call_onreset_when_manually_resetting_circuit()
        {
            int onBreakCalled = 0;
            int onResetCalled = 0;
            Action <Exception, TimeSpan> onBreak = (_, __) => { onBreakCalled++; };
            Action onReset = () => { onResetCalled++; };

            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak, onBreak, onReset);

            onBreakCalled.Should().Be(0);
            breaker.Isolate();
            onBreakCalled.Should().Be(1);

            breaker.CircuitState.Should().Be(CircuitState.Isolated);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true)))
            .ShouldThrow <IsolatedCircuitException>();

            onResetCalled.Should().Be(0);
            breaker.Reset();
            onResetCalled.Should().Be(1);

            breaker.CircuitState.Should().Be(CircuitState.Closed);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true))).ShouldNotThrow();
        }
Ejemplo n.º 2
0
        public void Should_halfopen_circuit_after_the_specified_duration_has_passed()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);

            // duration has passed, circuit now half open
            breaker.CircuitState.Should().Be(CircuitState.HalfOpen);
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
        }
Ejemplo n.º 3
0
        public void Should_call_onbreak_when_breaking_circuit_first_time_but_not_for_subsequent_calls_through_open_circuit()
        {
            int onBreakCalled = 0;
            Action <Exception, TimeSpan> onBreak = (_, __) => { onBreakCalled++; };
            Action onReset = () => { };

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak, onReset);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Closed);
            onBreakCalled.Should().Be(0);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Open);
            onBreakCalled.Should().Be(1);

            // call through circuit when already broken - should not retrigger onBreak
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();

            breaker.CircuitState.Should().Be(CircuitState.Open);
            onBreakCalled.Should().Be(1);
        }
Ejemplo n.º 4
0
        public void Should_be_able_to_reset_automatically_opened_circuit_without_specified_duration_passing()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            // reset circuit, with no time having passed
            breaker.Reset();
            SystemClock.UtcNow().Should().Be(time);
            breaker.CircuitState.Should().Be(CircuitState.Closed);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true))).ShouldNotThrow();
        }
Ejemplo n.º 5
0
        public void Should_call_onreset_with_the_passed_context()
        {
            IDictionary <string, object> contextData = null;

            Action <Exception, TimeSpan, Context> onBreak = (_, __, ___) => { };
            Action <Context> onReset = context => { contextData = context; };

            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak, onBreak, onReset);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);
            breaker.CircuitState.Should().Be(CircuitState.HalfOpen);

            // first call after duration should invoke onReset, with context
            breaker.ExecuteAsync(() => Task.FromResult(true), new { key1 = "value1", key2 = "value2" }.AsDictionary());

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
Ejemplo n.º 6
0
        public void Should_report_cancellation_during_faulting_action_execution_when_user_delegate_does_not_observe_cancellationtoken()
        {
            var durationOfBreak          = TimeSpan.FromMinutes(1);
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 1,
                AttemptDuringWhichToCancel    = 1,
                ActionObservesCancellation    = false
            };

            breaker.Awaiting(x => x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException>(scenario, cancellationTokenSource, onExecute))
            .ShouldThrow <TaskCanceledException>()
            .And.CancellationToken.Should().Be(cancellationToken);

            attemptsInvoked.Should().Be(1);
        }
Ejemplo n.º 7
0
        public void Should_honour_and_report_cancellation_during_func_execution()
        {
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            bool?result = null;

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 0,
                AttemptDuringWhichToCancel    = 1,
                ActionObservesCancellation    = true
            };

            breaker.Awaiting(async x => result = await x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException, bool>(scenario, cancellationTokenSource, onExecute, true).ConfigureAwait(false))
            .ShouldThrow <TaskCanceledException>().And.CancellationToken.Should().Be(cancellationToken);

            result.Should().Be(null);

            attemptsInvoked.Should().Be(1);
        }
Ejemplo n.º 8
0
        public void Should_not_execute_action_when_cancellationtoken_cancelled_before_execute()
        {
            var durationOfBreak          = TimeSpan.FromMinutes(1);
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 0,
                AttemptDuringWhichToCancel    = null, // Cancellation token cancelled manually below - before any scenario execution.
            };

            cancellationTokenSource.Cancel();

            breaker.Awaiting(x => x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException>(scenario, cancellationTokenSource, onExecute))
            .ShouldThrow <TaskCanceledException>()
            .And.CancellationToken.Should().Be(cancellationToken);

            attemptsInvoked.Should().Be(0);
        }
Ejemplo n.º 9
0
        public void Should_execute_func_returning_value_when_cancellationtoken_not_cancelled()
        {
            var durationOfBreak          = TimeSpan.FromMinutes(1);
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            bool?result = null;

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 0,
                AttemptDuringWhichToCancel    = null,
            };

            breaker.Awaiting(async x => result = await x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException, bool>(scenario, cancellationTokenSource, onExecute, true).ConfigureAwait(false))
            .ShouldNotThrow();

            result.Should().BeTrue();

            attemptsInvoked.Should().Be(1);
        }
Ejemplo n.º 10
0
        public void Should_honour_different_cancellationtoken_captured_implicitly_by_action()
        {
            // Before CancellationToken support was built in to Polly, users of the library may have implicitly captured a CancellationToken and used it to cancel actions.  For backwards compatibility, Polly should not confuse these with its own CancellationToken; it should distinguish TaskCanceledExceptions thrown with different CancellationTokens.

            var durationOfBreak          = TimeSpan.FromMinutes(1);
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            CancellationTokenSource policyCancellationTokenSource = new CancellationTokenSource();
            CancellationToken       policyCancellationToken       = policyCancellationTokenSource.Token;

            CancellationTokenSource implicitlyCapturedActionCancellationTokenSource = new CancellationTokenSource();
            CancellationToken       implicitlyCapturedActionCancellationToken       = implicitlyCapturedActionCancellationTokenSource.Token;

            implicitlyCapturedActionCancellationTokenSource.Cancel();

            int attemptsInvoked = 0;

            breaker.Awaiting(x => x.ExecuteAsync(async ct =>
            {
                attemptsInvoked++;
                await Task.FromResult(true);
                implicitlyCapturedActionCancellationToken.ThrowIfCancellationRequested();
            }, policyCancellationToken))
            .ShouldThrow <TaskCanceledException>()
            .And.CancellationToken.Should().Be(implicitlyCapturedActionCancellationToken);

            attemptsInvoked.Should().Be(1);
        }
Ejemplo n.º 11
0
        public void Should_call_onhalfopen_when_automatically_transitioning_to_halfopen_due_to_subsequent_execution()
        {
            int onBreakCalled    = 0;
            int onResetCalled    = 0;
            int onHalfOpenCalled = 0;
            Action <Exception, TimeSpan> onBreak = (_, __) => { onBreakCalled++; };
            Action onReset    = () => { onResetCalled++; };
            Action onHalfOpen = () => { onHalfOpenCalled++; };

            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak, onBreak, onReset, onHalfOpen);

            onBreakCalled.Should().Be(0);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            onBreakCalled.Should().Be(0);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            onBreakCalled.Should().Be(1);

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);
            onBreakCalled.Should().Be(1);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);
            // duration has passed, circuit now half open
            onHalfOpenCalled.Should().Be(0); // not yet transitioned to half-open, because we have not queried state

            // first call after duration is successful, so circuit should reset
            breaker.ExecuteAsync(() => Task.FromResult(true));
            onHalfOpenCalled.Should().Be(1);
            breaker.CircuitState.Should().Be(CircuitState.Closed);
            onResetCalled.Should().Be(1);
        }
Ejemplo n.º 12
0
        public void Should_not_open_circuit_if_exception_raised_is_not_the_specified_exception()
        {
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));

            breaker.Awaiting(x => x.RaiseExceptionAsync <ArgumentNullException>())
            .ShouldThrow <ArgumentNullException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <ArgumentNullException>())
            .ShouldThrow <ArgumentNullException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <ArgumentNullException>())
            .ShouldThrow <ArgumentNullException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);
        }
Ejemplo n.º 13
0
        public void Should_be_able_to_handle_a_duration_of_timespan_maxvalue()
        {
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(1, TimeSpan.MaxValue);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
        }
Ejemplo n.º 14
0
        public void Should_open_circuit_with_the_last_raised_exception_after_specified_number_of_specified_exception_have_been_raised()
        {
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>()
            .WithMessage("The circuit is now open and is not allowing calls.")
            .WithInnerException <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);
        }
Ejemplo n.º 15
0
        public void Context_should_be_empty_if_execute_not_called_with_any_context_data()
        {
            IDictionary <string, object> contextData = new { key1 = "value1", key2 = "value2" }.AsDictionary();

            Action <Exception, TimeSpan, Context> onBreak = (_, __, context) => { contextData = context; };
            Action <Context> onReset = _ => { };

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak, onReset);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Open);

            contextData.Should().BeEmpty();
        }
Ejemplo n.º 16
0
        public void Should_call_onhalfopen_when_automatically_transitioning_to_halfopen_due_to_state_read()
        {
            int onBreakCalled    = 0;
            int onResetCalled    = 0;
            int onHalfOpenCalled = 0;
            Action <Exception, TimeSpan> onBreak = (_, __) => { onBreakCalled++; };
            Action onReset    = () => { onResetCalled++; };
            Action onHalfOpen = () => { onHalfOpenCalled++; };

            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak, onBreak, onReset, onHalfOpen);

            onBreakCalled.Should().Be(0);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            onBreakCalled.Should().Be(0);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            onBreakCalled.Should().Be(1);

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);
            onBreakCalled.Should().Be(1);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);
            // duration has passed, circuit now half open
            breaker.CircuitState.Should().Be(CircuitState.HalfOpen);
            onHalfOpenCalled.Should().Be(1);
        }
Ejemplo n.º 17
0
        public void Should_call_onbreak_when_breaking_circuit_automatically()
        {
            bool onBreakCalled = false;
            Action <Exception, TimeSpan> onBreak = (_, __) => { onBreakCalled = true; };
            Action onReset = () => { };

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak, onReset);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Closed);
            onBreakCalled.Should().BeFalse();

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Open);
            onBreakCalled.Should().BeTrue();
        }
Ejemplo n.º 18
0
        public void Should_close_circuit_again_on_reset_after_manual_override()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Isolate();
            breaker.CircuitState.Should().Be(CircuitState.Isolated);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true)))
            .ShouldThrow <IsolatedCircuitException>();

            breaker.Reset();
            breaker.CircuitState.Should().Be(CircuitState.Closed);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true))).ShouldNotThrow();
        }
Ejemplo n.º 19
0
        public void Should_create_new_context_for_each_call_to_execute()
        {
            string contextValue = null;

            Action <Exception, TimeSpan, Context> onBreak = (_, __, context) => { contextValue = context.ContainsKey("key") ? context["key"].ToString() : null; };
            Action <Context> onReset = context => { contextValue = context.ContainsKey("key") ? context["key"].ToString() : null; };

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak, onReset);

            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>(new { key = "original_value" }.AsDictionary()))
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);
            contextValue.Should().Be("original_value");

            SystemClock.UtcNow = () => time.Add(durationOfBreak);

            // duration has passed, circuit now half open
            breaker.CircuitState.Should().Be(CircuitState.HalfOpen);
            // but not yet reset

            // first call after duration is successful, so circuit should reset
            breaker.ExecuteAsync(() => Task.FromResult(true), new { key = "new_value" }.AsDictionary());
            breaker.CircuitState.Should().Be(CircuitState.Closed);
            contextValue.Should().Be("new_value");
        }
Ejemplo n.º 20
0
        public void Should_report_cancellation_when_both_open_circuit_and_cancellation()
        {
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(1, TimeSpan.FromMinutes(1));

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>()
            .WithMessage("The circuit is now open and is not allowing calls.")
            .WithInnerException <DivideByZeroException>();
            // Circuit is now broken.

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            cancellationTokenSource.Cancel();

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 1,
                AttemptDuringWhichToCancel    = null, // Cancelled manually instead - see above.
                ActionObservesCancellation    = false
            };

            breaker.Awaiting(x => x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException>(scenario, cancellationTokenSource, onExecute))
            .ShouldThrow <TaskCanceledException>()
            .And.CancellationToken.Should().Be(cancellationToken);

            attemptsInvoked.Should().Be(0);
        }
Ejemplo n.º 21
0
        public void Should_call_onbreak_with_the_passed_context()
        {
            IDictionary <string, object> contextData = null;

            Action <Exception, TimeSpan, Context> onBreak = (_, __, context) => { contextData = context; };
            Action <Context> onReset = _ => { };

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak, onReset);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>(
                                 new { key1 = "value1", key2 = "value2" }.AsDictionary()
                                 )).ShouldThrow <DivideByZeroException>();

            breaker.CircuitState.Should().Be(CircuitState.Open);

            contextData.Should()
            .ContainKeys("key1", "key2").And
            .ContainValues("value1", "value2");
        }
Ejemplo n.º 22
0
        public async Task Should_reset_circuit_after_the_specified_duration_has_passed_if_the_next_call_does_not_raise_an_exception()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            // 2 exception raised, circuit is now open
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);

            // duration has passed, circuit now half open
            breaker.CircuitState.Should().Be(CircuitState.HalfOpen);
            // first call after duration is successful, so circuit should reset
            await breaker.ExecuteAsync(() => Task.FromResult(0));

            breaker.CircuitState.Should().Be(CircuitState.Closed);

            // circuit has been reset so should once again allow 2 exceptions to be raised before breaking
            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <DivideByZeroException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);

            breaker.Awaiting(x => x.RaiseExceptionAsync <DivideByZeroException>())
            .ShouldThrow <BrokenCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Open);
        }
Ejemplo n.º 23
0
        public void Should_hold_circuit_open_despite_elapsed_time_if_manual_override_open()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.CircuitState.Should().Be(CircuitState.Closed);

            breaker.Isolate();
            breaker.CircuitState.Should().Be(CircuitState.Isolated);

            SystemClock.UtcNow = () => time.Add(durationOfBreak);
            breaker.CircuitState.Should().Be(CircuitState.Isolated);
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true)))
            .ShouldThrow <IsolatedCircuitException>();
        }
Ejemplo n.º 24
0
        public void Should_open_circuit_and_block_calls_if_manual_override_open()
        {
            var time = 1.January(2000);

            SystemClock.UtcNow = () => time;

            var durationOfBreak = TimeSpan.FromMinutes(1);

            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            breaker.CircuitState.Should().Be(CircuitState.Closed);

            // manually break circuit
            breaker.Isolate();
            breaker.CircuitState.Should().Be(CircuitState.Isolated);

            // circuit manually broken: execution should be blocked; even non-exception-throwing executions should not reset circuit
            breaker.Awaiting(x => x.ExecuteAsync(() => Task.FromResult(true)))
            .ShouldThrow <IsolatedCircuitException>();
            breaker.CircuitState.Should().Be(CircuitState.Isolated);
        }
Ejemplo n.º 25
0
        public void Should_execute_action_when_non_faulting_and_cancellationtoken_not_cancelled()
        {
            var durationOfBreak          = TimeSpan.FromMinutes(1);
            CircuitBreakerPolicy breaker = Policy
                                           .Handle <DivideByZeroException>()
                                           .CircuitBreakerAsync(2, durationOfBreak);

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            int    attemptsInvoked = 0;
            Action onExecute       = () => attemptsInvoked++;

            Scenario scenario = new Scenario
            {
                NumberOfTimesToRaiseException = 0,
                AttemptDuringWhichToCancel    = null,
            };

            breaker.Awaiting(x => x.RaiseExceptionAndOrCancellationAsync <DivideByZeroException>(scenario, cancellationTokenSource, onExecute))
            .ShouldNotThrow();

            attemptsInvoked.Should().Be(1);
        }