Skip to main content

Retry logic and circuit breakers with an identical API in Python and TypeScript.

Project description

retrykit (Python)

Retry logic and circuit breakers with an identical API in Python and TypeScript.

  • @retry decorator and Retrying context manager
  • ✅ Built-in circuit breaker (CLOSED → OPEN → HALF_OPEN → CLOSED)
  • ✅ Sync and async, transparently
  • ✅ Automatic OpenTelemetry spans when opentelemetry-api is installed
  • ✅ Zero required dependencies, fully typed (py.typed)

Install

pip install retrykit
# with OpenTelemetry spans:
pip install "retrykit[otel]"

Quick start

from retrykit import retry

@retry(attempts=3)
async def call_api() -> str:
    ...

Full options

@retry(
    attempts=5,
    backoff="exponential",   # "fixed" | "linear" | "exponential"
    delay=1.0,               # base delay in seconds
    max_delay=60.0,
    jitter=True,             # full jitter to avoid thundering herd
    on=["HTTPError", "TimeoutError"],  # retry only on these (class or name)
    on_retry=lambda attempt, error: print(f"Retry {attempt}: {error}"),
)
async def call_openai(prompt: str) -> str:
    ...

Circuit breaker

from retrykit import circuit_breaker, CircuitBreaker, CircuitOpenError

@circuit_breaker(threshold=5, timeout=30, on_open=lambda: print("opened!"))
async def call_stripe(): ...

# Or standalone:
breaker = CircuitBreaker(threshold=5, timeout=30)
result = breaker.call(do_work)          # sync
result = await breaker.call_async(work) # async
print(breaker.state)                    # CircuitState.CLOSED / OPEN / HALF_OPEN

Composable

@retry(attempts=3, backoff="exponential")
@circuit_breaker(threshold=5, timeout=30)
async def resilient_call(): ...

Context-manager style

from retrykit import Retrying

async with Retrying(attempts=3, backoff="exponential") as r:
    async for attempt in r:
        with attempt:
            result = await call_api()

The sync form is identical without the async keywords:

with Retrying(attempts=3) as r:
    for attempt in r:
        with attempt:
            result = call_api()

API reference

retry(attempts=3, *, backoff="exponential", delay=1.0, max_delay=60.0, jitter=False, on=None, on_retry=None)

Decorator. Retries up to attempts times. Raises RetryError (with .last_exception) when exhausted. on accepts exception classes or their string names; None retries on any Exception.

Retrying(...)

Same options as retry; usable as a sync or async context manager / iterator.

circuit_breaker(threshold=5, timeout=30, *, on_open=None, on_close=None)

Decorator. The underlying CircuitBreaker is exposed on the wrapped function as .breaker. Raises CircuitOpenError while open.

CircuitBreaker(threshold=5, timeout=30.0, *, on_open=None, on_close=None)

.call(fn, *a, **kw), await .call_async(fn, *a, **kw), .state, .failure_count, .reset().

OpenTelemetry

If opentelemetry-api is importable, every attempt is wrapped in a span named retry.attempt:<func> with attributes retry.attempt, retry.max_attempts, and retry.failed. If it is not installed, span creation is silently skipped — no configuration required.

Development

pip install -e ".[dev]"
pytest --cov=retrykit
mypy
ruff check retrykit

License

MIT

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

retrykit_lib-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

retrykit_lib-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file retrykit_lib-0.1.0.tar.gz.

File metadata

  • Download URL: retrykit_lib-0.1.0.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for retrykit_lib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4cfc80e9a0096e188f7f4d966903f29bd72568a46e2941a5ab25315831e76dd6
MD5 cf0088d802bbd144c78daed9e071c002
BLAKE2b-256 41db08389ccafc057cc587cf797ded5c9fb748b3dbe599a897af9efd55455a34

See more details on using hashes here.

File details

Details for the file retrykit_lib-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: retrykit_lib-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for retrykit_lib-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f8ac9074609a79db62d7fa1bc6820c2cb7849b853c2929df297df57eec2f087b
MD5 56ec3478ca9c74340a20c6e92c029f35
BLAKE2b-256 33cd57347d06397fef34afab8e9e3ceab2c08ebc503274408e2aec885d756154

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page