Class CircuitBreaker<T>
java.lang.Object
io.github.teceli.resiliencia.patterns.circuitbreaker.CircuitBreaker<T>
- All Implemented Interfaces:
Resilient<T>
CircuitBreaker pattern: track recent call outcomes in a sliding window and stop calling a
failing or slow downstream once the failure or slow-call rate crosses its threshold,
rejecting calls immediately instead of piling more load onto something already struggling.
Holds live state (the current
CircuitState and its sliding window). Immutable in
configuration and thread-safe by design — share one instance across all callers that must
observe the same outcomes. Each withX method returns a new, independent CircuitBreaker,
starting back in the Closed state with an empty window.-
Nested Class Summary
Nested classes/interfaces inherited from interface io.github.teceli.resiliencia.core.api.Resilient
Resilient.Operation<T> -
Method Summary
Modifier and TypeMethodDescriptioncall(Resilient.Operation<T> operation) Execute an operation with resilience guarantees.static <T> CircuitBreaker<T> ACircuitBreakeridentified byname, starting Closed with the default thresholds and window size.outcome(Resilient.Operation<T> operation) Execute an operation and capture the result or failure as an Outcome.The kind of this pattern, used for internal comparisons (e.g.The name of this pattern, e.g.state()The current state, computed fresh on each call: forCircuitState.Open, the returnedremainingWaitreflects the time left until a HalfOpen test call is attempted, not the originally configuredwaitDurationInOpenState.Use a customClockinstead of the system clock, e.g. a manual/virtual clock in tests to make wait-duration and half-open transition assertions deterministic and instant.withFailureRateThreshold(double failureRateThreshold) Fraction of recorded calls that must fail, once the sliding window is full, to open the circuit.withIgnoreOn(List<Class<? extends Throwable>> ignoreOn) Exception types that are never recorded as failures, even if also matched bywithRecordOn(java.util.List<java.lang.Class<? extends java.lang.Throwable>>).withListener(ResilienceEvent.Listener listener) Add a listener notified of everyCircuitBreakerEventemitted by this instance.withPermittedCallsInHalfOpenState(int permittedCallsInHalfOpenState) Number of test calls allowed through while HalfOpen.withRecordOn(List<Class<? extends Throwable>> recordOn) Exception types that count as failures.withRecordOnResult(Predicate<T> recordOnResult) Predicate evaluated against a successful return value to record it as a failure anyway, even though no exception was thrown — e.g. an HTTP client returning a 200 with an error body.withSlidingWindowSize(int slidingWindowSize) Number of most recent calls used to compute the failure and slow-call rates.withSlowCallDurationThreshold(Duration slowCallDurationThreshold) What counts as a slow call.withSlowCallRateThreshold(double slowCallRateThreshold) Fraction of recorded calls that must exceedwithSlowCallDurationThreshold(java.time.Duration), once the sliding window is full, to open the circuit.withWaitDurationInOpenState(Duration waitDurationInOpenState) How long the circuit stays Open before moving to HalfOpen to try test calls again.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface io.github.teceli.resiliencia.core.api.Resilient
callAsync, hasOwnDeadline
-
Method Details
-
of
ACircuitBreakeridentified byname, starting Closed with the default thresholds and window size. Refine viawithXmethods, e.g.withFailureRateThreshold(double)to change when the circuit opens. -
withFailureRateThreshold
Fraction of recorded calls that must fail, once the sliding window is full, to open the circuit. Must be between 0.0 (exclusive) and 1.0. Default: 0.5. -
withSlowCallRateThreshold
Fraction of recorded calls that must exceedwithSlowCallDurationThreshold(java.time.Duration), once the sliding window is full, to open the circuit. Must be between 0.0 (exclusive) and 1.0. Default: 1.0 (slow calls alone never open the circuit unless every call is slow). -
withSlowCallDurationThreshold
What counts as a slow call. Default: no limit — no call is ever counted as slow. -
withSlidingWindowSize
Number of most recent calls used to compute the failure and slow-call rates. Thresholds are only evaluated once this many calls have been recorded. Default: 10. -
withWaitDurationInOpenState
How long the circuit stays Open before moving to HalfOpen to try test calls again. Default: 60 seconds. -
withPermittedCallsInHalfOpenState
Number of test calls allowed through while HalfOpen. All must succeed for the circuit to close; any failure reopens it. Default: 3. -
withRecordOn
Exception types that count as failures. Default: anyException. A type also listed inwithIgnoreOn(java.util.List<java.lang.Class<? extends java.lang.Throwable>>)is not recorded — ignoreOn takes precedence. -
withIgnoreOn
Exception types that are never recorded as failures, even if also matched bywithRecordOn(java.util.List<java.lang.Class<? extends java.lang.Throwable>>). -
withRecordOnResult
Predicate evaluated against a successful return value to record it as a failure anyway, even though no exception was thrown — e.g. an HTTP client returning a 200 with an error body. If the predicate itself throws, that is logged as a warning and treated asfalse— a broken predicate never turns a successful call into a reported failure. Default: no result is ever recorded as a failure. -
withListener
Add a listener notified of everyCircuitBreakerEventemitted by this instance. Listener exceptions are logged and otherwise ignored — a broken listener never affects the outcome. -
withClock
Use a customClockinstead of the system clock, e.g. a manual/virtual clock in tests to make wait-duration and half-open transition assertions deterministic and instant. -
state
The current state, computed fresh on each call: forCircuitState.Open, the returnedremainingWaitreflects the time left until a HalfOpen test call is attempted, not the originally configuredwaitDurationInOpenState.For
CircuitState.HalfOpen,permitsIssuedandsuccessesare read from two independent atomics, not under a single lock, so this is a best-effort, non-atomic snapshot: a concurrent test call can complete between the two reads, meaning the pair of values returned may never have existed together at any single instant. -
patternKind
Description copied from interface:ResilientThe kind of this pattern, used for internal comparisons (e.g. Policy order validation). UnlikeResilient.patternName(), which is a free-form observability label, this is a closed enum the library can reason about exhaustively. Defaults toPatternKind.CUSTOMfor user-defined Resilient implementations.- Specified by:
patternKindin interfaceResilient<T>
-
patternName
Description copied from interface:ResilientThe name of this pattern, e.g. "retry", "timeout", "circuit-breaker". Used for identification (e.g. by Policy) without coupling to concrete pattern types. Defaults to "custom" for user-defined Resilient implementations.- Specified by:
patternNamein interfaceResilient<T>
-
call
Description copied from interface:ResilientExecute an operation with resilience guarantees. May throw ResilienciaException or a specific pattern exception.- Specified by:
callin interfaceResilient<T>- Throws:
ResilientException
-
outcome
Description copied from interface:ResilientExecute an operation and capture the result or failure as an Outcome. Never throws for a recordedException— always returns Success, Failure, or a pattern-specific outcome. AnErrorthrown by the operation propagates uncaught instead of being captured as a Failure: fatal JVM conditions (e.g.OutOfMemoryError) should not be treated as a recoverable result.
-