0.13.0 — time-based failure-rate circuit-breaker mode
httpware 0.13.0 — time-based failure-rate trip mode for the circuit breaker
Minor release. Additive only — no breaking changes.
This release adds an opt-in time-based failure-rate trip mode to both
AsyncCircuitBreaker and CircuitBreaker. Classic consecutive-failure behavior
is the default and is unchanged.
New behavior
The classic circuit breaker trips after failure_threshold consecutive counted
failures — a simple and effective policy for hard outages. It can miss partial
degradation, though: a downstream returning errors on half of all requests may
never form a long enough consecutive streak to trip the circuit.
Rate mode addresses this. Pass failure_rate_threshold to switch:
from httpware import AsyncClient
from httpware.middleware.resilience import AsyncCircuitBreaker
breaker = AsyncCircuitBreaker(
failure_rate_threshold=0.5, # open at ≥50% failures
window_seconds=30.0, # over a rolling 30s window
minimum_calls=20, # but only once 20+ calls are observed
)
async with AsyncClient(
base_url="https://api.example.com",
middleware=[breaker],
) as client:
response = await client.get("/users/1")The circuit opens when the observed failure rate over the rolling window_seconds
window meets or exceeds failure_rate_threshold — but only once minimum_calls
outcomes have been recorded in that window. The minimum_calls guard prevents a
single early failure from immediately tripping the circuit before a meaningful
sample has accumulated.
New constructor parameters
Both AsyncCircuitBreaker and CircuitBreaker accept three new keyword
arguments:
| Parameter | Default | Effect |
|---|---|---|
failure_rate_threshold |
None |
Float in (0, 1]. When set, switches the breaker to rate mode. None keeps classic consecutive-failure mode. ≤0 or >1 raises ValueError. |
window_seconds |
30.0 |
Rolling window width for rate mode. Ignored in classic mode. ≤0 raises ValueError. |
minimum_calls |
20 |
Minimum outcomes in the window before the rate is evaluated. Ignored in classic mode. <1 raises ValueError. |
In rate mode, failure_threshold is ignored — the trip condition is purely
rate-based. All other parameters (reset_timeout, success_threshold,
failure_status_codes) apply in both modes.
Observability
Event names are identical in both modes: circuit.opened, circuit.rejected,
circuit.half_open, circuit.closed. In rate mode the circuit.opened event
carries additional attributes — failure_rate, failure_rate_threshold,
window_seconds, observed_calls — and its message is
"circuit opened — failure rate threshold reached".
What is NOT in this release
The following remain deferred and are not part of 0.13.0:
- Count-based sliding windows (the current implementation is time-based only)
- Slow-call detection (a separate trip axis based on latency percentiles)
- Manual circuit control (
force_open,force_closed) - State introspection properties on the breaker instance
Shipped via
PR #69 — time-based failure-rate trip mode for the circuit breaker.