Resilience¶
Quickstart¶
Add retry to a flaky call with one decorator:
from attune.resilience import retry
@retry(max_attempts=3, initial_delay=0.1)
def load_value() -> int:
return 42
print(load_value())
Tasks¶
Retry a flaky call with backoff¶
from attune.resilience import retry
@retry(max_attempts=5, backoff_factor=2.0, initial_delay=0.1)
def fetch() -> str:
return "ok"
print(fetch())
Verify: the function runs normally on success; on exception it
retries up to max_attempts, sleeping initial_delay *
backoff_factor**n (capped at max_delay, with jitter).
Guard a dependency with a circuit breaker¶
from attune.resilience import circuit_breaker, get_circuit_breaker
@circuit_breaker(name="api", failure_threshold=5, reset_timeout=30.0)
def call_api() -> str:
return "ok"
print(call_api())
print(get_circuit_breaker("api").get_stats())
Verify: get_circuit_breaker("api") returns the registered
CircuitBreaker; get_stats() reports name, state,
failure_count, success_count, time_until_reset. After
failure_threshold consecutive failures the breaker opens and calls
raise CircuitOpenError until reset_timeout passes.
Bound a call with a timeout¶
from attune.resilience import timeout
@timeout(seconds=5.0)
def quick() -> str:
return "done"
print(quick())
Verify: returns normally within the bound; raises
ResilienceTimeoutError (or returns the fallback) on overrun.
Fall back to alternates¶
import asyncio
from attune.resilience import fallback, with_fallback
@fallback(lambda: "from-fallback") # decorator: synchronous
def risky() -> str:
raise RuntimeError("primary failed")
print(risky())
def primary() -> str:
raise ValueError("boom")
safe = with_fallback(primary, [lambda: "backup"]) # returns async wrapper
print(asyncio.run(safe()))
Verify: the @fallback decorator returns the first alternate's
result synchronously; with_fallback(...) returns an async callable
— await it (here via asyncio.run).
Aggregate component health¶
from attune.resilience import HealthCheck
hc = HealthCheck()
@hc.register("db") # register is a decorator
def check_db() -> bool:
return True
health = hc.run_all_sync()
print(health.status, health.to_dict())
Verify: register(name, ...) is a decorator — apply it over a
check function (returning a bool/dict), not as register(name, fn).
run_all_sync() returns a SystemHealth whose status is a
HealthStatus and to_dict() serializes the result; run_all() is the
async variant.
Reference¶
| Symbol | Kind | Purpose |
|---|---|---|
retry(max_attempts=3, backoff_factor=2.0, initial_delay=1.0, max_delay=60.0, jitter=True, retryable_exceptions=None, on_retry=None) |
decorator | Retry with backoff. |
RetryConfig(...) / retry_with_backoff(func, *a, config=None) |
class / fn | Retry config + imperative runner. |
circuit_breaker(name=None, failure_threshold=5, reset_timeout=60.0, half_open_max_calls=3, ...) |
decorator | Circuit breaker. |
CircuitBreaker(name, ...) / get_circuit_breaker(name) |
class / fn | Breaker object + registry lookup. |
CircuitState |
enum | CLOSED / OPEN / HALF_OPEN. |
CircuitOpenError |
exception | Raised when the breaker is open. |
timeout(seconds, error_message=None, fallback=None) |
decorator | Bound a call. |
with_timeout(coro, seconds, fallback_value=None) |
async fn | Bound a coroutine. |
ResilienceTimeoutError |
exception | Raised on overrun. |
fallback(*fns, default=None, log_failures=True) |
decorator (sync) | Try alternates. |
with_fallback(primary, fallbacks, default=None) |
fn → async wrapper | Programmatic fallback chain. |
Fallback(name, functions, default_value=None) |
class | add / execute. |
HealthCheck(version="unknown") |
class | register(name, timeout=10.0, critical=False) decorator, run_all (async), run_all_sync. |
HealthStatus / SystemHealth |
enum / class | HEALTHY/DEGRADED/UNHEALTHY/UNKNOWN; aggregate result. |