public async Task TestMultipleTimeWindowRetriesBeforeClosingCircuit() { var key = "cmd-H"; var sleepWindow = 400; HystrixCommand <bool> cmd1 = new FailureCommand(key, 0); var cb = cmd1._circuitBreaker; var stream = HealthCountsStream.GetInstance(HystrixCommandKeyDefault.AsKey(key), cmd1.CommandOptions); Assert.True(WaitForHealthCountToUpdate(key, 1000, output), "Health count stream failed to start"); // this should start as allowing requests Assert.True(cb.AllowRequest, Time.CurrentTimeMillis + " Request NOT allowed when expected!"); Assert.False(cb.IsOpen, Time.CurrentTimeMillis + " Circuit breaker is open when it should be closed!"); _ = await cmd1.ExecuteAsync(); HystrixCommand <bool> cmd2 = new FailureCommand(key, 0); _ = await cmd2.ExecuteAsync(); HystrixCommand <bool> cmd3 = new FailureCommand(key, 0); _ = await cmd3.ExecuteAsync(); HystrixCommand <bool> cmd4 = new TimeoutCommand(key); _ = await cmd4.ExecuteAsync(); // everything has failed in the test window so we should return false now // Allow window to pass, // Time.Wait(200); Assert.True(WaitForHealthCountToUpdate(key, 250, output), "Health count stream failed to update"); output.WriteLine(Time.CurrentTimeMillis + " !!!! 1 4 failures, circuit will open on recalc"); // Assert.False(cb.AllowRequest, "Request allowed when NOT expected!"); Assert.True(cb.IsOpen, Time.CurrentTimeMillis + " Circuit is closed when it should be open!"); // wait for sleepWindow to pass output.WriteLine(Time.CurrentTimeMillis + " !!!! 2 Sleep window starting where all commands fail-fast"); Time.Wait(sleepWindow + 50); output.WriteLine(Time.CurrentTimeMillis + " !!!! 3 Sleep window over, should allow singleTest()"); // but the circuit should still be open Assert.True(cb.IsOpen, Time.CurrentTimeMillis + " Circuit is closed when it should be open!"); // we should now allow 1 request, and upon failure, should not affect the circuit breaker, which should remain open HystrixCommand <bool> cmd5 = new FailureCommand(key, 50); var asyncResult5 = cmd5.Observe(); output.WriteLine(Time.CurrentTimeMillis + " !!!! Kicked off the single-test"); // and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed when NOT expected!"); output.WriteLine(Time.CurrentTimeMillis + " !!!! Confirmed that no other requests go out during single-test"); await asyncResult5.SingleAsync(); output.WriteLine(Time.CurrentTimeMillis + " !!!! SingleTest just completed"); // all requests should still be blocked, because the singleTest failed Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (1) when NOT expected!"); Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (2) when NOT expected!"); Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (3) when NOT expected!"); // wait for sleepWindow to pass output.WriteLine(Time.CurrentTimeMillis + " !!!! 2nd sleep window START"); Time.Wait(sleepWindow + 50); output.WriteLine(Time.CurrentTimeMillis + " !!!! 2nd sleep window over"); // we should now allow 1 request, and upon failure, should not affect the circuit breaker, which should remain open HystrixCommand <bool> cmd6 = new FailureCommand(key, 50); var asyncResult6 = cmd6.Observe(); output.WriteLine(Time.CurrentTimeMillis + " 2nd singleTest just kicked off"); // and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed when NOT expected!"); Assert.False(await asyncResult6.SingleAsync()); output.WriteLine(Time.CurrentTimeMillis + " 2nd singleTest now over"); // all requests should still be blocked, because the singleTest failed Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (1) when NOT expected!"); Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (2) when NOT expected!"); Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed (3) when NOT expected!"); // wait for sleepWindow to pass Time.Wait(sleepWindow); // but the circuit should still be open Assert.True(cb.IsOpen, Time.CurrentTimeMillis + " Circuit is closed when it should be open!"); // we should now allow 1 request, and upon success, should cause the circuit to be closed HystrixCommand <bool> cmd7 = new SuccessCommand(key, 50); var asyncResult7 = cmd7.Observe(); // and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest, Time.CurrentTimeMillis + " Request allowed when NOT expected!"); await asyncResult7.SingleAsync(); // all requests should be open again Assert.True(cb.AllowRequest, Time.CurrentTimeMillis + " Request NOT allowed (1) when expected!"); Assert.True(cb.AllowRequest, Time.CurrentTimeMillis + " Request NOT allowed (2) when expected!"); Assert.True(cb.AllowRequest, Time.CurrentTimeMillis + " Request NOT allowed (3) when expected!"); // and the circuit should be closed again Assert.False(cb.IsOpen, Time.CurrentTimeMillis + " Circuit breaker is open when it should be closed!"); // and the circuit should be closed again Assert.False(cb.IsOpen, Time.CurrentTimeMillis + " Circuit breaker is open when it should be closed!"); }
public async void TestMultipleTimeWindowRetriesBeforeClosingCircuit() { String key = "cmd-H"; try { int sleepWindow = 200; HystrixCommand <Boolean> cmd1 = new FailureCommand(key, 60); IHystrixCircuitBreaker cb = cmd1.circuitBreaker; // this should start as allowing requests Assert.True(cb.AllowRequest); Assert.False(cb.IsOpen); cmd1.Execute(); HystrixCommand <Boolean> cmd2 = new FailureCommand(key, 1); cmd2.Execute(); HystrixCommand <Boolean> cmd3 = new FailureCommand(key, 1); cmd3.Execute(); HystrixCommand <Boolean> cmd4 = new TimeoutCommand(key); cmd4.Execute(); // everything has failed in the test window so we should return false now output.WriteLine("!!!! 1 4 failures, circuit will open on recalc"); Time.Wait(150); Assert.False(cb.AllowRequest); Assert.True(cb.IsOpen); // wait for sleepWindow to pass output.WriteLine("!!!! 2 Sleep window starting where all commands fail-fast"); Time.Wait(sleepWindow + 50); output.WriteLine("!!!! 3 Sleep window over, should allow singleTest()"); // but the circuit should still be open Assert.True(cb.IsOpen); // we should now allow 1 request, and upon failure, should not affect the circuit breaker, which should remain open HystrixCommand <bool> cmd5 = new FailureCommand(key, 60); IObservable <bool> asyncResult5 = cmd5.Observe(); output.WriteLine("!!!! Kicked off the single-test"); // and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest); output.WriteLine("!!!! Confirmed that no other requests go out during single-test"); await asyncResult5.SingleAsync(); output.WriteLine("!!!! SingleTest just completed"); // all requests should still be blocked, because the singleTest failed Assert.False(cb.AllowRequest); Assert.False(cb.AllowRequest); Assert.False(cb.AllowRequest); // wait for sleepWindow to pass output.WriteLine("!!!! 2nd sleep window START"); Time.Wait(sleepWindow + 50); output.WriteLine("!!!! 2nd sleep window over"); // we should now allow 1 request, and upon failure, should not affect the circuit breaker, which should remain open HystrixCommand <bool> cmd6 = new FailureCommand(key, 60); IObservable <bool> asyncResult6 = cmd6.Observe(); output.WriteLine("2nd singleTest just kicked off"); //and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest); output.WriteLine("confirmed that 2nd singletest only happened once"); await asyncResult6.SingleAsync(); output.WriteLine("2nd singleTest now over"); // all requests should still be blocked, because the singleTest failed Assert.False(cb.AllowRequest); Assert.False(cb.AllowRequest); Assert.False(cb.AllowRequest); // wait for sleepWindow to pass Time.Wait(sleepWindow + 50); // but the circuit should still be open Assert.True(cb.IsOpen); // we should now allow 1 request, and upon success, should cause the circuit to be closed HystrixCommand <bool> cmd7 = new SuccessCommand(key, 60); IObservable <bool> asyncResult7 = cmd7.Observe(); // and further requests are still blocked while the singleTest command is in flight Assert.False(cb.AllowRequest); await asyncResult7.SingleAsync(); // all requests should be open again Assert.True(cb.AllowRequest); Assert.True(cb.AllowRequest); Assert.True(cb.AllowRequest); // and the circuit should be closed again Assert.False(cb.IsOpen); // and the circuit should be closed again Assert.False(cb.IsOpen); } catch (Exception e) { output.WriteLine(e.ToString()); Assert.False(true, "Error occurred: " + e.Message); } }