@@ -142,6 +142,11 @@ public ILogger Logger {
142142 /// </summary>
143143 public TimeSpan Timeout { get ; set ; }
144144
145+ /// <summary>
146+ /// Gets or sets the circuit breaker for this pipeline.
147+ /// </summary>
148+ public ICircuitBreaker CircuitBreaker { get ; set ; }
149+
145150 public async ValueTask ExecuteAsync ( Func < CancellationToken , ValueTask > action , CancellationToken cancellationToken = default )
146151 {
147152 if ( action == null )
@@ -168,7 +173,7 @@ public async ValueTask ExecuteAsync(Func<CancellationToken, ValueTask> action, C
168173 }
169174 catch ( Exception ex )
170175 {
171- if ( ( ShouldRetry != null && ! ShouldRetry ( attempts , ex ) ) || attempts >= maxAttempts )
176+ if ( ( ShouldRetry != null && ! ShouldRetry ( attempts , ex ) ) || attempts >= maxAttempts || ( CircuitBreaker != null && CircuitBreaker . IsBroken ( ) ) )
172177 throw ;
173178
174179 _logger ? . LogError ( ex , "Retry error: {Message}" , ex . Message ) ;
@@ -209,7 +214,7 @@ public async ValueTask<T> ExecuteAsync<T>(Func<CancellationToken, ValueTask<T>>
209214 }
210215 catch ( Exception ex )
211216 {
212- if ( ( ShouldRetry != null && ! ShouldRetry ( attempts , ex ) ) || attempts >= maxAttempts )
217+ if ( ( ShouldRetry != null && ! ShouldRetry ( attempts , ex ) ) || attempts >= maxAttempts || ( CircuitBreaker != null && CircuitBreaker . IsBroken ( ) ) )
213218 throw ;
214219
215220 _logger ? . LogError ( ex , "Retry error: {Message}" , ex . Message ) ;
@@ -257,6 +262,42 @@ private TimeSpan GetInterval(int attempts)
257262 private static readonly Random _random = new ( ) ;
258263}
259264
265+ public interface ICircuitBreaker
266+ {
267+ bool IsBroken ( ) ;
268+ void IncrementSuccess ( ) ;
269+ void IncrementFailure ( ) ;
270+ }
271+
272+ public class FoundatioCircuitBreaker : ICircuitBreaker
273+ {
274+ public FoundatioCircuitBreaker ( TimeSpan ? samplingDuration = null , double failureRatio = 0.5 , int minimumThroughput = 10 , TimeSpan ? breakDuration = null )
275+ {
276+ SamplingDuration = samplingDuration ?? TimeSpan . FromSeconds ( 30 ) ;
277+ FailureRatio = failureRatio ;
278+ MinimumThroughput = minimumThroughput ;
279+ BreakDuration = breakDuration ?? TimeSpan . FromSeconds ( 30 ) ;
280+ }
281+
282+ public TimeSpan SamplingDuration { get ; }
283+ public double FailureRatio { get ; }
284+ public int MinimumThroughput { get ; }
285+ public TimeSpan BreakDuration { get ; }
286+
287+ public CircuitState State { get ; private set ; } = CircuitState . Closed ;
288+
289+ public bool IsBroken ( ) => throw new NotImplementedException ( ) ;
290+ public void IncrementSuccess ( ) => throw new NotImplementedException ( ) ;
291+ public void IncrementFailure ( ) => throw new NotImplementedException ( ) ;
292+ }
293+
294+ public enum CircuitState
295+ {
296+ Closed ,
297+ Open ,
298+ HalfOpen
299+ }
300+
260301public class FoundatioResiliencePipelineBuilder ( FoundatioResiliencePipeline pipeline )
261302{
262303 /// <summary>
0 commit comments