public void Should_open_circuit_with_the_last_handled_result_after_specified_number_of_exceptions_and_results_have_been_raised__when_configuring_multiple_results_and_exceptions() { CircuitBreakerPolicy <ResultPrimitive> breaker = Policy .Handle <DivideByZeroException>() .OrResult(ResultPrimitive.Fault) .Or <ArgumentException>() .OrResult(ResultPrimitive.FaultAgain) .CircuitBreaker(4, TimeSpan.FromMinutes(1)); breaker.Invoking(b => b.RaiseResultAndOrExceptionSequence(new DivideByZeroException())) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.RaiseResultSequence(ResultPrimitive.Fault) .Should().Be(ResultPrimitive.Fault); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(b => b.RaiseResultAndOrExceptionSequence(new ArgumentException())) .ShouldThrow <ArgumentException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.RaiseResultSequence(ResultPrimitive.FaultAgain) .Should().Be(ResultPrimitive.FaultAgain); breaker.CircuitState.Should().Be(CircuitState.Open); // 4 exception raised, circuit is now open breaker.Invoking(b => b.RaiseResultSequence(ResultPrimitive.Good)) .ShouldThrow <BrokenCircuitException <ResultPrimitive> >() .WithMessage("The circuit is now open and is not allowing calls.") .Where(e => e.Result == ResultPrimitive.FaultAgain); breaker.CircuitState.Should().Be(CircuitState.Open); }
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); }
static void setup() { breakerPolicy = Policy .HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode) .CircuitBreakerAsync(2, TimeSpan.FromSeconds(5), OnBreak, OnReset, OnHalfOpen); }
public PollyQoSProvider(DownstreamReRoute reRoute, IOcelotLoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger <PollyQoSProvider>(); Enum.TryParse(reRoute.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy); _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptions.TimeoutValue), strategy); _circuitBreakerPolicy = Policy .Handle <HttpRequestException>() .Or <TimeoutRejectedException>() .Or <TimeoutException>() .CircuitBreakerAsync( exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking, durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak), onBreak: (ex, breakDelay) => { _logger.LogError( ".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex); }, onReset: () => { _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."); }, onHalfOpen: () => { _logger.LogDebug(".Breaker logging: Half-open; next call is a trial."); } ); CircuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy); }
/// <summary> /// Constructor /// </summary> /// <param name="options"></param> /// <param name="useCircuit"></param> public AzureBlobRetryProviderWithCircuitBreaker(CircuitBreakerOptions options, bool useCircuit) { _options = options; _fallback = GetFallbackPolicy(); _circuitBreaker = GetCircuitBreakerPolicy(); _useCircuit = useCircuit; }
public void Should_not_open_circuit_if_result_returned_does_not_match_any_of_the_result_predicates() { CircuitBreakerPolicy <ResultClass> breaker = Policy .Handle <ArgumentException>(e => e.ParamName == "key") .OrResult <ResultClass>(r => r.ResultCode == ResultPrimitive.Fault) .CircuitBreaker(2, TimeSpan.FromMinutes(1)); // non-matched result predicate breaker.RaiseResultSequence(new ResultClass(ResultPrimitive.FaultAgain)) .ResultCode.Should().Be(ResultPrimitive.FaultAgain); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.RaiseResultSequence(new ResultClass(ResultPrimitive.FaultAgain)) .ResultCode.Should().Be(ResultPrimitive.FaultAgain); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.RaiseResultSequence(new ResultClass(ResultPrimitive.FaultAgain)) .ResultCode.Should().Be(ResultPrimitive.FaultAgain); breaker.CircuitState.Should().Be(CircuitState.Closed); // non-matched exception predicate breaker.Invoking(b => b.RaiseResultAndOrExceptionSequence(new ArgumentException("message", "value"))) .ShouldThrow <ArgumentException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(b => b.RaiseResultAndOrExceptionSequence(new ArgumentException("message", "value"))) .ShouldThrow <ArgumentException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(b => b.RaiseResultAndOrExceptionSequence(new ArgumentException("message", "value"))) .ShouldThrow <ArgumentException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); }
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>() .CircuitBreaker(2, durationOfBreak, onBreak, onReset); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.Invoking(x => x.RaiseException <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.Execute(() => { }, new { key1 = "value1", key2 = "value2" }.AsDictionary()); contextData.Should() .ContainKeys("key1", "key2").And .ContainValues("value1", "value2"); }
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>() .CircuitBreaker(2, durationOfBreak, onBreak, onReset); onBreakCalled.Should().Be(0); breaker.Isolate(); onBreakCalled.Should().Be(1); breaker.CircuitState.Should().Be(CircuitState.Isolated); breaker.Invoking(x => x.Execute(() => { })) .ShouldThrow <IsolatedCircuitException>(); onResetCalled.Should().Be(0); breaker.Reset(); onResetCalled.Should().Be(1); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(x => x.Execute(() => { })).ShouldNotThrow(); }
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>() .CircuitBreaker(2, TimeSpan.FromMinutes(1), onBreak, onReset); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); onBreakCalled.Should().Be(0); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Open); onBreakCalled.Should().Be(1); // call through circuit when already broken - should not retrigger onBreak breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <BrokenCircuitException>(); breaker.CircuitState.Should().Be(CircuitState.Open); onBreakCalled.Should().Be(1); }
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>() .CircuitBreaker(2, durationOfBreak); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Open); // 2 exception raised, circuit is now open breaker.Invoking(x => x.RaiseException <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.Invoking(x => x.Execute(() => { })).ShouldNotThrow(); }
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>() .CircuitBreaker(2, durationOfBreak); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Closed); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); breaker.CircuitState.Should().Be(CircuitState.Open); // 2 exception raised, circuit is now open breaker.Invoking(x => x.RaiseException <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.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region Other ways of injecting policies //IAsyncPolicy<HttpResponseMessage> httpRetryPolicy = // Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode).RetryAsync(3); //services.AddHttpClient("RemoteServer", client => //{ // client.BaseAddress = new Uri("http://aspnetmonsters.com"); // //client.DefaultRequestHeaders.Add("Accept", "application/json"); //}).AddPolicyHandler(httpRetryPolicy); #endregion #region Advanced Circuit Breaker //CircuitBreakerPolicy<HttpResponseMessage> breakerPolicy = Policy // .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode) // .AdvancedCircuitBreakerAsync(0.5, TimeSpan.FromSeconds(60), 7, TimeSpan.FromSeconds(15), // OnBreak, OnReset, OnHalfOpen); #endregion CircuitBreakerPolicy <HttpResponseMessage> breakerPolicy = Policy .HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode) .CircuitBreakerAsync(2, TimeSpan.FromSeconds(10), OnBreak, OnReset, OnHalfOpen); BulkheadPolicy <HttpResponseMessage> bulkheadIsolationPolicy = Policy .BulkheadAsync <HttpResponseMessage>(2, 4, onBulkheadRejectedAsync: OnBulkheadRejectedAsync); services.AddHttpClient("RemoteServer", client => { client.BaseAddress = new Uri("http://aspnetmonsters.com"); //client.DefaultRequestHeaders.Add("Accept", "application/json"); }); services.AddHttpClient("InventoryClient", client => { client.BaseAddress = new Uri("http://localhost:57697/api/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("Accept", "application/json"); }). ConfigurePrimaryHttpMessageHandler(handler => new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip }); IAsyncPolicy <HttpResponseMessage> httpRetryPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode) .RetryAsync(3); services.AddSingleton <IAsyncPolicy <HttpResponseMessage> >(httpRetryPolicy); services.AddSingleton <CircuitBreakerPolicy <HttpResponseMessage> >(breakerPolicy); services.AddSingleton <BulkheadPolicy <HttpResponseMessage> >(bulkheadIsolationPolicy); services.AddSingleton(CustomPolicyWrap()); services.AddSingleton <PolicyHolder>(new PolicyHolder()); services.AddSingleton <IPolicyRegistry <string> >(GetRegistry()); services.AddMvc(); }
public void Should_be_able_to_handle_a_duration_of_timespan_maxvalue() { CircuitBreakerPolicy breaker = Policy .Handle <DivideByZeroException>() .CircuitBreaker(1, TimeSpan.MaxValue); breaker.Invoking(x => x.RaiseException <DivideByZeroException>()) .ShouldThrow <DivideByZeroException>(); }
public ActionResult <int> Get(int id) { // For demo purposes, a GET will trip circuit breaker CircuitBreakerPolicy breaker = registry.Get <CircuitBreakerPolicy>("DefaultBreaker"); breaker.Isolate(); // And trip another health check. Very buggy GET method :) return(healthCheck.Trip()); }
public void Should_initialise_to_closed_state() { var durationOfBreak = TimeSpan.FromMinutes(1); CircuitBreakerPolicy breaker = Policy .Handle <DivideByZeroException>() .CircuitBreaker(2, durationOfBreak); breaker.CircuitState.Should().Be(CircuitState.Closed); }
/// <summary> /// CTOR /// </summary> /// <param name="strategy"></param> public CircutBreakerHandler(CircutBreakerStrategy strategy) { CircuitBreakerPolicy circutBreakerPolicy = Policy .Handle <TException>() .CircuitBreakerAsync(strategy.AllowedExceptionsCount, strategy.CooldownTimeout, (exception, count) => strategy.OnRetry?.Invoke(exception), strategy.OnReset); strategy.Reset = circutBreakerPolicy.Reset; strategy.Isolate = circutBreakerPolicy.Isolate; Policy = circutBreakerPolicy; }
public void GetPolicyTPolicy_should_return_null_if_none_match_predicate() { CircuitBreakerPolicy policyA = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); Policy policyB = Policy.Handle <Exception>().Retry(); CircuitBreakerPolicy policyC = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); PolicyWrap wrap = policyA.Wrap(policyB.Wrap(policyC)); wrap.GetPolicy <CircuitBreakerPolicy>(p => p.CircuitState == CircuitState.Open).Should().BeNull(); }
public void Should_initialise_LastHandledResult_and_LastResult_to_default_on_creation() { CircuitBreakerPolicy <ResultPrimitive> breaker = Policy .Handle <DivideByZeroException>() .OrResult(ResultPrimitive.Fault) .CircuitBreaker(2, TimeSpan.FromMinutes(1)); breaker.LastHandledResult.Should().Be(default(ResultPrimitive)); breaker.LastException.Should().BeNull(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { CircuitBreakerPolicy <ISearchResponse <InventoryItem> > breakerPolicy = Polly.Policy .HandleResult <ISearchResponse <InventoryItem> >(r => !r.IsValid) .CircuitBreaker(2, TimeSpan.FromSeconds(5), OnBreak, OnReset, onHalfOpen: OnHalfOpen); services.AddSingleton <CircuitBreakerPolicy <ISearchResponse <InventoryItem> > >(breakerPolicy); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
public void Should_initialise_to_closed_state() { var durationOfBreak = TimeSpan.FromMinutes(1); CircuitBreakerPolicy <ResultPrimitive> breaker = Policy .HandleResult(ResultPrimitive.Fault) .CircuitBreaker(2, durationOfBreak); breaker.CircuitState.Should().Be(CircuitState.Closed); }
public void Should_be_able_to_handle_a_duration_of_timespan_maxvalue() { CircuitBreakerPolicy <ResultPrimitive> breaker = Policy .HandleResult(ResultPrimitive.Fault) .CircuitBreaker(1, TimeSpan.MaxValue); var result = breaker.RaiseResultSequence(ResultPrimitive.Fault); result.Should().Be(ResultPrimitive.Fault); }
/// <summary> /// <para> Builds a <see cref="Policy"/> that will function like a Circuit Breaker.</para> /// <para>The circuit will break after <paramref name="exceptionsAllowedBeforeBreaking"/> /// exceptions that are handled by this policy are raised. The circuit will stay /// broken for the <paramref name="durationOfBreak"/>. Any attempt to execute this policy /// while the circuit is broken, will immediately throw a <see cref="BrokenCircuitException"/> containing the exception /// that broke the cicuit. /// </para> /// <para>If the first action after the break duration period results in an exception, the circuit will break /// again for another <paramref name="durationOfBreak"/>, otherwise it will reset. /// </para> /// </summary> /// <param name="policyBuilder">The policy builder.</param> /// <param name="exceptionsAllowedBeforeBreaking">The number of exceptions that are allowed before opening the circuit.</param> /// <param name="durationOfBreak">The duration the circuit will stay open before resetting.</param> /// <returns>The policy instance.</returns> /// <remarks>(see "Release It!" by Michael T. Nygard fi)</remarks> /// <exception cref="System.ArgumentOutOfRangeException">exceptionsAllowedBeforeBreaking;Value must be greater than zero.</exception> public static Policy CircuitBreaker(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak) { if (exceptionsAllowedBeforeBreaking <= 0) { throw new ArgumentOutOfRangeException("exceptionsAllowedBeforeBreaking", "Value must be greater than zero."); } var policyState = new CircuitBreakerState(exceptionsAllowedBeforeBreaking, durationOfBreak); return(new Policy(action => CircuitBreakerPolicy.Implementation(action, policyBuilder.ExceptionPredicates, policyState))); }
public FlurlWrapperClient(IFlurlClientFactory clientFactory, IOptions <FlurlWrapperClientSettings> appSettings, string url) { _client = clientFactory.Get(url); _circuitBreaker = Policy .Handle <FlurlHttpException>() .Or <FlurlHttpTimeoutException>() .CircuitBreakerAsync( exceptionsAllowedBeforeBreaking: appSettings.Value.PollyCircuitBreakExceptionCount, durationOfBreak: TimeSpan.FromSeconds(appSettings.Value.PollyCircuitBreakDurationInSeconds)); }
static void TryExecutingRiskyOperation(CircuitBreakerPolicy breaker) { try { breaker.Execute(() => { CloudOperation(); }); } catch (Exception) { Console.WriteLine("TryExecutingRiskyOperation - got exception"); } }
static void Wrap() { bool check = false; RetryPolicy waitAndRetryPolicy = Policy .Handle <Exception>() .Retry(6, onRetry: (exception, retryCount) => { Console.WriteLine($"====Retry===== : 呼叫 API 異常, 進行第 {retryCount} 次重試"); if (retryCount == 5) { check = true; } }); TimeoutPolicy timeoutPolicys = Policy .Timeout(TimeSpan.FromMilliseconds(1000), TimeoutStrategy.Pessimistic, onTimeout: (context, timespan, task) => { Console.WriteLine($"====TimeOut===== : execution timed out after {timespan} seconds."); }); FallbackPolicy <String> fallbackForAnyException = Policy <String> .Handle <Exception>() .Fallback( fallbackAction: () => { Console.WriteLine("999999999"); return("123"); }, onFallback: e => { Console.WriteLine($"[Polly fallback] : 重試失敗, say goodbye"); } ); CircuitBreakerPolicy circuitPolicy = Policy .Handle <Exception>() .CircuitBreaker(3, TimeSpan.FromSeconds(0), (ex, ts) => { Console.WriteLine($"====CircuitBreaker [OnBreak]===== ts = {ts.Seconds}s ,ex.message = {ex.Message}"); }, () => { Console.WriteLine("AService OnReset"); }); try { PolicyWrap <String> policyWrap = fallbackForAnyException .Wrap(waitAndRetryPolicy) .Wrap(circuitPolicy) .Wrap(timeoutPolicys); policyWrap.Execute(() => doMockHTTPRequest(check)); } catch (Exception ex) { Console.WriteLine(ex); } }
public void GetPolicyTPolicy_should_return_single_policy_of_type_TPolicy_matching_predicate() { CircuitBreakerPolicy policyA = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); Policy policyB = Policy.Handle <Exception>().Retry(); CircuitBreakerPolicy policyC = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); policyA.Isolate(); PolicyWrap wrap = policyA.Wrap(policyB.Wrap(policyC)); wrap.GetPolicy <CircuitBreakerPolicy>(p => p.CircuitState == CircuitState.Closed).Should().BeSameAs(policyC); }
public void GetPoliciesTPolicy_should_return_policies_of_type_TPolicy_matching_predicate() { CircuitBreakerPolicy policyA = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); Policy policyB = Policy.Handle <Exception>().Retry(); CircuitBreakerPolicy policyC = Policy.Handle <Exception>().CircuitBreaker(1, TimeSpan.Zero); policyA.Isolate(); PolicyWrap wrap = policyA.Wrap(policyB.Wrap(policyC)); wrap.GetPolicies <CircuitBreakerPolicy>(p => p.CircuitState == CircuitState.Closed).ShouldBeEquivalentTo(new[] { policyC }, options => options.WithStrictOrdering()); }
public PollyResiliencyPolicy(ResiliencyParameters parameters) { circuitBreakerPolicy = Policy.Handle <T>().AdvancedCircuitBreakerAsync( failureThreshold: parameters.CircuitBreakerFailureThreshold, samplingDuration: TimeSpan.FromSeconds(parameters.CircuitBreakerDurationOfBreak), minimumThroughput: parameters.CircuitBreakerSamplingDuration, durationOfBreak: TimeSpan.FromSeconds(parameters.CircuitBreakerMinimumThroughput)); retryPolicy = Policy.Handle <T>().RetryAsync(parameters.NumberOfRetries); this.policies = Policy.WrapAsync(circuitBreakerPolicy, retryPolicy); }
/// <summary> /// <para>Builds the policy that will "break the circuit" after <paramref name="countBeforeBreaking"/> /// exceptions that could be handled by the <paramref name="syntax"/> being built. The circuit /// stays broken for the <paramref name="duration"/>. Any attempt to /// invoke method within the policy, while the circuit is broken, will immediately re-throw /// the last exception. </para> /// <para>If the action fails within the policy after the block period, then the breaker /// is blocked again for the next <paramref name="duration"/>. /// It will be reset, otherwise.</para> /// </summary> /// <param name="syntax">The syntax.</param> /// <param name="duration">How much time the breaker will stay open before resetting</param> /// <param name="countBeforeBreaking">How many exceptions are needed to break the circuit</param> /// <returns>shared policy instance</returns> /// <remarks>(see "ReleaseIT!" for the details)</remarks> public static ActionPolicyWithState CircuitBreaker(this Syntax <ExceptionHandler> syntax, TimeSpan duration, int countBeforeBreaking) { Enforce.Argument(() => syntax); Enforce.Argument(() => countBeforeBreaking, Is.GreaterThan(0)); Enforce.Argument(() => duration, Is.NotDefault); var state = new CircuitBreakerState(duration, countBeforeBreaking); var syncLock = new CircuitBreakerStateLock(state); return(new ActionPolicyWithState(action => CircuitBreakerPolicy.Implementation(action, syntax.Target, syncLock))); }
public ResilientApiClient(string baseUrl) { this.apiClient = new ApiClient(baseUrl); this.circuitBreaker = Policy .HandleInner <HttpRequestException>() .CircuitBreaker( exceptionsAllowedBeforeBreaking: 3, durationOfBreak: TimeSpan.FromSeconds(5), onBreak: (exception, retryIn) => OnBreak(retryIn), onReset: () => OnReset()); }