Circuit Breaker¶
techrevati.runtime.circuit_breaker ¶
Circuit Breaker — Fault-tolerant execution with state machine.
Implements the Circuit Breaker pattern to prevent cascading failures when calling unreliable services or operations. Transitions between CLOSED (normal), OPEN (failing), and HALF_OPEN (testing) states.
Thread-safe with configurable failure threshold, recovery timeout,
and number of in-flight probes permitted in HALF_OPEN. Uses
time.monotonic for duration checks so clock jumps don't affect
behavior; the clock function is injectable for deterministic tests.
CircuitState ¶
Bases: str, Enum
Circuit breaker lifecycle states.
CircuitOpenError ¶
Bases: Exception
Raised when circuit breaker is open and request is blocked.
CircuitBreaker
dataclass
¶
CircuitBreaker(name, failure_threshold=5, recovery_timeout_seconds=60.0, half_open_max_probes=1, clock=time.monotonic)
Stateful circuit breaker with thread-safe transitions.
Parameters¶
name:
Human-readable identifier (included in CircuitOpenError).
failure_threshold:
Consecutive failures before the circuit opens.
recovery_timeout_seconds:
Duration the circuit stays open before allowing probes.
half_open_max_probes:
Concurrent probe calls allowed in HALF_OPEN. Default 1 (Polly
convention); raising to N spreads recovery risk over multiple
in-flight calls (Resilience4j defaults to 10).
clock:
Monotonic time source. Defaults to time.monotonic. Override
in tests to make timing-dependent behavior deterministic.
call ¶
Execute fn with breaker protection. Raises CircuitOpenError if open.
In HALF_OPEN state, at most half_open_max_probes concurrent
calls are admitted; excess callers receive CircuitOpenError
until in-flight probes complete.
AsyncCircuitBreaker
dataclass
¶
AsyncCircuitBreaker(name, failure_threshold=5, recovery_timeout_seconds=60.0, half_open_max_probes=1, clock=time.monotonic)
Async sibling of CircuitBreaker — same state semantics, asyncio.Lock.
Independent from the sync variant: state is not shared. Choose one per downstream. The probe-serialization, monotonic clock, and clock-injection contracts match the sync class exactly so behavior is portable between sync and async code paths.