Skip to content

feat(circuit-breaker): time-based failure-rate trip mode (0.13.0)#69

Merged
lesnik512 merged 9 commits into
mainfrom
feat/circuit-breaker-rate-mode
Jun 16, 2026
Merged

feat(circuit-breaker): time-based failure-rate trip mode (0.13.0)#69
lesnik512 merged 9 commits into
mainfrom
feat/circuit-breaker-rate-mode

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Adds an opt-in time-based failure-rate trip mode to AsyncCircuitBreaker / CircuitBreaker. The classic consecutive-failure model stays the default and is byte-unchanged. Rate mode opens the circuit when the failure rate over a rolling time window meets a threshold, once a minimum call volume is observed — catching partial degradation (e.g. a steady 50% error rate that never forms a consecutive streak) that the classic breaker misses.

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
)

Closes the deferred "CircuitBreaker v2 (a)" item. Ships as 0.13.0 (additive, no breaking changes).

What's in it

  • _RollingWindow — time-bucketed success/failure counters (10 buckets), eviction-on-read/write, with a Hypothesis property test.
  • Config + validationfailure_rate_threshold (opt-in switch, range (0,1]), window_seconds (30.0), minimum_calls (20); threaded through the shared _CircuitBreakerState so both clients reach parity.
  • Trip integration — rate mode changes only the CLOSED→OPEN decision (records every outcome, opens when total ≥ minimum_calls and failures/total ≥ threshold); checked after both successes and failures. Half-open recovery + event names identical to classic; window cleared on close. Mode-aware circuit.opened message + rate attributes.
  • Docsarchitecture/resilience.md, docs/resilience.md, module docstring, and 0.13.0 release notes.

Time-based (not count-based) was chosen because it matches the HTTP-service mental model and degrades sanely under variable traffic; Hystrix/Polly/Envoy are all time-based. Count-based windows, the slow-call axis, and manual control / state introspection remain deliberately deferred.

Design + plan: planning/changes/active/2026-06-16.02-circuit-breaker-rate-mode/.

Test plan

  • just test — 699 passed, 100% coverage
  • just lint — clean (ruff format/check + ty)
  • Behavior tests (async + sync): trips on partial failure, no trip below minimum_calls, time eviction, clear-on-close; validation; observability attribute set
  • Hypothesis property test for the rolling-window recorder
  • Classic-mode tests unchanged (no regression)
  • mkdocs build --strict — clean

🤖 Generated with Claude Code

lesnik512 and others added 9 commits June 16, 2026 13:02
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Design + plan for the opt-in time-based failure-rate trip mode, and the
Active Index entry. Bundle stays active/draft until merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ship bookkeeping for PR #69: fill the 0.13.0 release-notes PR number, mark
the bundle shipped (pr: 69), move it from changes/active/ to changes/archive/,
flip its Index line to Archived, and trim the deferred "CircuitBreaker v2" item
to the still-open axes (count-based window, manual control + state).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…validation

Address PR #69 review: note that failure_rate_threshold is the sole mode
switch (both-set → rate wins, not an error), and that window_seconds /
minimum_calls are validated in both modes even when inert in classic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit 2087b68 into main Jun 16, 2026
5 checks passed
@lesnik512 lesnik512 deleted the feat/circuit-breaker-rate-mode branch June 16, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant