Skip to main content

Retries that get out of your way. Decorators and helpers for sync and async retry with backoff, jitter, and circuit breaker.

Project description

tryr

Retries that get out of your way.

A small, focused retry library for Python. Decorators and context managers for sync and async code, with backoff strategies, jitter, hooks, and an optional circuit breaker. Zero required dependencies.

Why

  • tenacity is mature but has 40+ parameters.
  • backoff hasn't been updated since 2019 and async support is awkward.
  • You just want a clean decorator that retries on the right exceptions, sleeps with a sensible backoff, and gets out of your way.

That's tryr.

Install

pip install tryr

Quick start

from tryr import retry

@retry(max_attempts=5, retry_on=(ConnectionError, TimeoutError))
def fetch_user(user_id: int) -> dict:
    return requests.get(f"https://api.example.com/users/{user_id}").json()

Async version:

from tryr import aretry

@aretry(max_attempts=3, backoff="exponential", jitter="full")
async def fetch_async(url: str) -> dict:
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as r:
            return await r.json()

Backoff strategies

@retry(backoff="fixed", initial_delay=1.0)               # 1, 1, 1, ...
@retry(backoff="linear", initial_delay=0.5, max_delay=10) # 0.5, 1.0, 1.5, ...
@retry(backoff="exponential", initial_delay=0.5, max_delay=30)  # 0.5, 1, 2, 4, 8, 16, 30, ...

Add jitter to avoid thundering herd:

@retry(backoff="exponential", jitter="full")   # random in [0, delay]
@retry(backoff="exponential", jitter="equal")  # delay/2 + random(0, delay/2)

Exception classification

By default, tryr retries on Exception if you don't specify retry_on. Be explicit in real code:

@retry(
    retry_on=(requests.RequestException, TimeoutError),
    give_up_on=(requests.HTTPError,),  # 4xx won't be retried
)
def fetch(): ...

Hooks

@retry(
    max_attempts=5,
    on_retry=lambda attempt, exc, delay: logger.warning(
        "attempt %d failed: %s (sleeping %.2fs)", attempt, exc, delay
    ),
    on_give_up=lambda attempts, exc: metrics.counter("retries.give_up").inc(),
)
def f(): ...

Circuit breaker

Stop hammering a dead service:

from tryr import circuit_breaker

@circuit_breaker(failure_threshold=5, reset_timeout=30.0)
@retry(max_attempts=3)
def call_external_api(): ...

After 5 consecutive failures the breaker opens for 30 seconds, during which calls fail fast with CircuitOpenError. Then it half-opens for a probe call.

Context manager

For blocks that aren't functions:

from tryr import Retrier

with Retrier(max_attempts=3, backoff="exponential") as r:
    while r.should_retry():
        try:
            do_thing()
            break
        except TransientError as e:
            r.record_failure(e)

Development

git clone https://github.com/wowori/tryr
cd tryr
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[dev]"
pytest

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

tryr-0.1.0.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

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

tryr-0.1.0-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tryr-0.1.0.tar.gz
  • Upload date:
  • Size: 12.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tryr-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a9cf8de537c3a5206a1ef13567c75a6220988f9819c8ca0936e0f949fbda4881
MD5 9b28544fdd0dd0122310649d0e3050f4
BLAKE2b-256 c86b52abce543e18594fb1fd87295b2f60e2fea46642ec3e8f917fdbb7dfd294

See more details on using hashes here.

Provenance

The following attestation bundles were made for tryr-0.1.0.tar.gz:

Publisher: publish.yml on wowori/tryr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: tryr-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tryr-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2c6d2dda07b08a73ba1b408e1069e1998b9fa6cfa5eeae636519d65cebea2051
MD5 e974134890dd6cd8edfb3fb18d2a6214
BLAKE2b-256 1a2949af2c807c9ff0db78c1d30d8cc6bd686a7fea9f227955ce16e8e6938ad9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tryr-0.1.0-py3-none-any.whl:

Publisher: publish.yml on wowori/tryr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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