A composable retry policy framework with classification, jitter strategies, and observability hooks.
Project description
reflexio
Composable, low-overhead retry policies with pluggable classification, per-class backoff strategies, and structured observability hooks.
Designed for services that need predictable retry behavior and clean integration with metrics/logging.
Installation
From PyPI:
uv pip install reflexio
# or
pip install reflexio
Quick Start
from reflexio.policy import RetryPolicy
from reflexio.classify import default_classifier
from reflexio.strategies import decorrelated_jitter
policy = RetryPolicy(
classifier=default_classifier,
strategy=decorrelated_jitter(max_s=10.0),
)
def flaky():
# your operation that may fail
...
result = policy.call(flaky)
Decorator quick start
from reflexio import retry, default_classifier
from reflexio.strategies import decorrelated_jitter
@retry(
classifier=default_classifier,
strategy=decorrelated_jitter(max_s=5.0),
)
def fetch_user():
...
Async quick start
import asyncio
from reflexio import AsyncRetryPolicy, default_classifier
from reflexio.strategies import decorrelated_jitter
async_policy = AsyncRetryPolicy(
classifier=default_classifier,
strategy=decorrelated_jitter(max_s=5.0),
)
async def flaky_async():
...
asyncio.run(async_policy.call(flaky_async))
Why reflexio?
Most retry libraries give you either:
- decorators with a fixed backoff model, or
- one global strategy for all errors.
reflexio gives you something different:
✔ Exception → coarse error class mapping
Provided via default_classifier.
✔ Per-class strategy dispatch
Each ErrorClass can use its own backoff logic.
✔ Dependency-free strategies with jitter
decorrelated_jitter, equal_jitter, token_backoff.
✔ Deadlines, max attempts, and separate caps for UNKNOWN
Deterministic retry envelopes.
✔ Clean observability hook
Single callback for:
success, retry, permanent_fail, deadline_exceeded, max_attempts_exceeded, max_unknown_attempts_exceeded.
Error Classes & Classification
PERMANENT
CONCURRENCY
RATE_LIMIT
SERVER_ERROR
TRANSIENT
UNKNOWN
Classification rules:
- Explicit reflexio error types
- Numeric codes (
err.statusorerr.code) - Name heuristics
- Fallback to UNKNOWN
Metrics & Observability
def metric_hook(event, attempt, sleep_s, tags):
print(event, attempt, sleep_s, tags)
policy.call(my_op, on_metric=metric_hook)
Backoff Strategies
Strategy signature:
(attempt: int, klass: ErrorClass, prev_sleep: Optional[float]) -> float
Built‑ins:
decorrelated_jitter()equal_jitter()token_backoff()
Per-Class Example
policy = RetryPolicy(
classifier=default_classifier,
strategy=decorrelated_jitter(max_s=10.0), # default
strategies={
ErrorClass.CONCURRENCY: decorrelated_jitter(max_s=1.0),
ErrorClass.RATE_LIMIT: decorrelated_jitter(max_s=60.0),
ErrorClass.SERVER_ERROR: equal_jitter(max_s=30.0),
},
)
Deadline & Attempt Controls
policy = RetryPolicy(
classifier=default_classifier,
strategy=decorrelated_jitter(),
deadline_s=60,
max_attempts=8,
max_unknown_attempts=2,
)
Development
uv run pytest
Examples (in docs/snippets/)
- Sync httpx demo:
uv pip install httpxthenuv run python docs/snippets/httpx_sync_retry.py - Async httpx demo using
AsyncRetryPolicy:uv pip install httpxthenuv run python docs/snippets/httpx_async_retry.py - Async worker loop with retries:
uv run python docs/snippets/async_worker_retry.py - Decorator usage (sync + async):
uv run python docs/snippets/decorator_retry.py - FastAPI proxy with metrics counter:
uv pip install "fastapi[standard]" httpxthenuv run uvicorn docs.snippets.fastapi_downstream:app --reload - PyODBC + SQLSTATE classification example:
uv pip install pyodbcthenuv run python docs/snippets/pyodbc_retry.py
Versioning
Semantic Versioning.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reflexio-0.2.1.tar.gz.
File metadata
- Download URL: reflexio-0.2.1.tar.gz
- Upload date:
- Size: 37.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bef963a26f611261288743472727e8d0302d6bd5368dc822c8ff563b1a418032
|
|
| MD5 |
d09edae52578f72d110e50d07e5e9252
|
|
| BLAKE2b-256 |
167e056968d244cc190d93bdc470548c6355f9c6d5fb1ab6404304ecb6c043d4
|
File details
Details for the file reflexio-0.2.1-py3-none-any.whl.
File metadata
- Download URL: reflexio-0.2.1-py3-none-any.whl
- Upload date:
- Size: 11.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d59700d90db3f9b97ee17c5a6385759ab51dcf529afa8f7872aee03ea73a8a86
|
|
| MD5 |
6caece42f1e6eae54953aa1371945701
|
|
| BLAKE2b-256 |
c7285d092b93eebdc612641d615158a740de7949976955f236517854936431ec
|