retry adds per-attempt timeout, retry/backoff, and optional semaphore-based concurrency control around async and sync callables. It works for ordinary functions without creating an EventBus.
Sync callables stay sync and block synchronously for retry sleeps and semaphore waits. Async callables stay async and await retry sleeps and semaphore waits.
Supported callable forms:
- Python: sync and async functions, methods, and lambdas via
@retry(...)orretry(...)(fn). - TypeScript: sync and async functions and arrow functions via
retry(...)(fn), plus sync and async class methods via@retry(...). - Rust: sync and async free functions and methods via
abxbus::retry!; call those retried functions from Rust closures such as EventBus handlers. - Go: retry is not implemented yet.
Signature
- Python
- TypeScript
- Rust
- Go
Options
Example: Standalone function
- Python
- TypeScript
- Rust
Example: Inline wrapper
- Python
- TypeScript
- Rust
- Go
Example: Decorated class method
- Python
- TypeScript
- Rust
- Go
Behavior
- Semaphore acquisition happens once per call, then all retry attempts run within that acquired slot.
- Backoff delay per retry is:
retry_after * retry_backoff_factor^(attempt - 1). - Retries stop immediately when the thrown error does not match
retry_on_errors. - Bus/event timeouts act as outer execution budgets;
retry.timeoutis per-attempt. - Sync wrappers return synchronously and block synchronously for retry sleeps and semaphore waits.
- Rust retry functions return
Result<T, E>whereE: From<abxbus::retry::RetryError>.
Runtime differences
- Python and TypeScript both support
multiprocess,global,class, andinstance. - Rust supports
multiprocess,global,class, andinstancethroughabxbus::retry!. - Go does not include
retryyet. - TypeScript uses async-context re-entrancy tracking in Node/Bun to avoid same-semaphore nested deadlocks.
retry_on_errorsmatching differs slightly:- Python: exception classes or compiled regex patterns (matched against
"ErrorClass: message"). - TypeScript: error constructors, error-name strings, or regex patterns.
- Rust: typed predicate function via
retry_if = should_retry.
- Python: exception classes or compiled regex patterns (matched against