# noretry A simple retry library for Rust with both sync and async support. ## Usage Async (enabled by default via the `tokio` feature): ```rust let result = noretry::retry_async(|| async { do_something().await }) .await .map_err(|e| e.into_inner())?; ``` Sync: ```rust let result = noretry::retry(|| { do_something() }) .map_err(|e| e.into_inner())?; ``` Both use sensible defaults: 3 attempts, exponential backoff, 100ms initial delay, 30s cap, and jitter. Errors returned from the closure are automatically treated as transient (retryable) via the `From` impl on `Retryable`. Use `?` as normal and retries happen transparently. ## Features The `tokio` feature is enabled by default, providing `retry_async` and `run_async`. To use only the sync API: ```toml noretry = { version = "0.1", default-features = false } ``` ## Builder For more control, use the builder with `run` (sync) or `run_async`: ```rust noretry::builder() .with_max_attempts(5) .with_linear_backoff() .build() .run_async(|| async { do_something().await }) .await?; ``` ## Backoff strategies Exponential backoff (default): ```rust noretry::builder() .with_exponential_backoff() .build() ``` Linear backoff: ```rust noretry::builder() .with_linear_backoff() .build() ``` Both strategies support configurable initial delay, max delay cap, and jitter (enabled by default): ```rust use std::time::Duration; noretry::builder() .with_initial_delay(Duration::from_millis(200)) .with_max_delay(Duration::from_secs(10)) .with_jitter(false) .build() ``` ## Permanent errors If an error should not be retried, mark it as permanent using `map_err`: ```rust use noretry::Retryable; noretry::builder() .build() .run_async(|| async { do_something() .await .map_err(Retryable::permanent)? }) .await; ``` The result is a `RetryError::Permanent` or `RetryError::Exhausted`, both of which carry the original error. Call `.into_inner()` to extract it.