Install & Compatibility
Where this runs
tested against v3.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.218s · 17.8MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.5s · import 0.184s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
retry
✓ from redo import retry
For functional usage
retriable
✓ from redo import retriable
For decorator usage
retrying
✓ from redo import retrying
For context manager usage
retry_async
✓ from redo import retry_async
For asynchronous functional usage
retriable_async
✓ from redo import retriable_async
For asynchronous decorator usage
This quickstart demonstrates using the `@retriable` decorator to automatically retry a potentially flaky function. It configures exponential backoff with jitter and specifies which exceptions should trigger a retry. The `attempt_num` argument in `flaky_operation` is illustrative and would typically be handled internally by `redo`'s retry mechanism counting attempts.
import random
import time
from redo import retriable
MAX_ATTEMPTS = 3
@retriable(
attempts=MAX_ATTEMPTS,
sleeptime=0.1, # initial sleep in seconds
max_sleeptime=1.0, # max sleep per retry
sleepscale=2, # exponential backoff factor
jitter=0.02, # random +/- seconds to add to sleeptime
retry_exceptions=(RuntimeError, ConnectionError) # specify exceptions to retry
)
def flaky_operation(attempt_num: int):
# Simulate a network call or I/O operation that might fail
if random.random() < 0.7 and attempt_num < MAX_ATTEMPTS: # 70% chance of failure for initial attempts
print(f"Attempt {attempt_num}: Operation failed, retrying...")
raise ConnectionError("Failed to connect to service")
print(f"Attempt {attempt_num}: Operation successful!")
return "Success"
if __name__ == "__main__":
print("Starting flaky operation...")
try:
result = flaky_operation(attempt_num=1)
print(f"Final result: {result}")
except Exception as e:
print(f"Operation ultimately failed after multiple retries: {e}")
Debug
Known issues
gotchaBy default, `redo.retriable` and `redo.retry` catch `Exception` if `retry_exceptions` is not specified. This can mask underlying issues that should not be retried, making debugging difficult.fixAlways explicitly define `retry_exceptions` to a tuple of specific exception types that are expected and can be resolved by retrying, e.g., `retry_exceptions=(ConnectionError, TimeoutError)`.
affects: All versions
gotchaMisconfiguring backoff parameters (`attempts`, `sleeptime`, `max_sleeptime`, `sleepscale`, `jitter`) can lead to excessive delays or a large number of retries, potentially overloading services or causing long wait times.fixCarefully test and tune backoff parameters to match the expected retry behavior and system load. Ensure `max_sleeptime` prevents indefinite waits and `attempts` limits overall retry count.
affects: All versions
gotchaIncorrectly mixing synchronous and asynchronous retry mechanisms (e.g., using `redo.retriable` with an `async def` function, or `redo.retriable_async` with a `def` function) will lead to runtime errors or unexpected behavior.fixAlways use the `_async` variants (`redo.retry_async`, `redo.retriable_async`) for `async def` callables and the non-`_async` variants for synchronous callables.
affects: All versions with async support
Upgrade
Version history
3.0.0latest on PyPI · released Jul 17, 2024
Audit
Dependencies
No dependency data recorded yet.