|
| 1 | +================================================== |
| 2 | +New Features (2026-06-19) — Resilience Primitives |
| 3 | +================================================== |
| 4 | + |
| 5 | +Reusable resilience primitives — a retry-with-backoff policy and a circuit |
| 6 | +breaker — plus an executor command that runs an action list through a named |
| 7 | +breaker. Pure standard library; both primitives take injectable |
| 8 | +``sleep`` / ``clock`` so they are unit-tested deterministically. |
| 9 | + |
| 10 | +(The existing ``AC_retry`` flow command already retries an action *body*; |
| 11 | +this adds the reusable :class:`RetryPolicy` callable wrapper and the new |
| 12 | +:class:`CircuitBreaker`.) |
| 13 | + |
| 14 | +.. contents:: |
| 15 | + :local: |
| 16 | + :depth: 2 |
| 17 | + |
| 18 | + |
| 19 | +RetryPolicy |
| 20 | +========== |
| 21 | + |
| 22 | +:: |
| 23 | + |
| 24 | + from je_auto_control import RetryPolicy, retry_call |
| 25 | + |
| 26 | + RetryPolicy(max_attempts=5, backoff=0.1, multiplier=2.0).run(flaky_fn) |
| 27 | + retry_call(flaky_fn, max_attempts=3) # convenience |
| 28 | + |
| 29 | +Retries ``func`` on the configured ``exceptions`` with exponential backoff |
| 30 | +(``backoff * multiplier**n``, optionally capped by ``max_backoff``), |
| 31 | +re-raising the last error when attempts are exhausted. |
| 32 | + |
| 33 | + |
| 34 | +CircuitBreaker |
| 35 | +============= |
| 36 | + |
| 37 | +:: |
| 38 | + |
| 39 | + from je_auto_control import CircuitBreaker, CircuitOpenError |
| 40 | + |
| 41 | + breaker = CircuitBreaker(failure_threshold=5, reset_timeout=30.0) |
| 42 | + try: |
| 43 | + breaker.call(call_remote_service) |
| 44 | + except CircuitOpenError: |
| 45 | + ... # short-circuited — the dependency is down |
| 46 | + |
| 47 | +Opens after ``failure_threshold`` consecutive failures and short-circuits |
| 48 | +(raising :class:`CircuitOpenError`) until ``reset_timeout`` elapses, then |
| 49 | +half-opens for one trial; a success closes it. Stops a retry storm from |
| 50 | +hammering a downed dependency. |
| 51 | + |
| 52 | +``AC_circuit_call`` / ``ac_circuit_call`` run an action list through a |
| 53 | +**named** breaker (state shared across calls), returning ``{state, record}``. |
0 commit comments