#retry #async #tokio #retry-async

try-again

Retry synchronous and asynchronous operations

2 releases

0.1.1 Feb 26, 2023
0.1.0 Feb 26, 2023

#911 in Asynchronous

Download history 17/week @ 2024-03-13 11/week @ 2024-03-20 34/week @ 2024-03-27 107/week @ 2024-04-03 100/week @ 2024-04-10 109/week @ 2024-04-17 211/week @ 2024-04-24 254/week @ 2024-05-01 182/week @ 2024-05-08 267/week @ 2024-05-15 148/week @ 2024-05-22 231/week @ 2024-05-29 126/week @ 2024-06-05 116/week @ 2024-06-12 247/week @ 2024-06-19 158/week @ 2024-06-26

696 downloads per month
Used in axum-keycloak-auth

MIT/Apache

16KB
280 lines

try-again

Retry synchronous or asynchronous operations until they no longer can or need to be retried.

Provides fn retry for retrying synchronous operations.

Provides async fn retry_async for retrying asynchronous operations.

The retried closure may return any type that implements NeedsRetry. This trait is already implemented for any Result and Option, allowing you to retry common fallible outcomes.

A retry strategy is required. The provided Retry type provides an implementation supporting

  • A maximum number of retries
  • A delay between retries being either:
    • None
    • A static delay
    • An exponentially increasing delay

A delay strategy is required and performs the actual delaying between executions of the users closure:

  • In the synchronous case: ThreadSleep {} can be used, blocking the current thread until the next try should take place.
  • In the asynchronous case: TokioSleep {} can be used when using the Tokio runtime.

Other delay strategies may be implemented to support async_std or other asynchronous runtimes.

Synchronous example

use try_again::{retry, Delay, Retry, ThreadSleep};

fn some_fallible_operation() -> Result<(), ()> {
    Ok(())
}

let final_outcome = retry(
    Retry {
        max_tries: 5,
        delay: Some(Delay::Static {
            delay: Duration::from_millis(125),
        }),
    },
    ThreadSleep {},
    move || some_fallible_operation(),
);

Asynchronous example

use try_again::{retry_async, Delay, Retry, TokioSleep};

async fn some_fallible_operation() -> Result<(), ()> {
    Ok(())
}

let final_outcome = retry_async(
    Retry {
        max_tries: 10,
        delay: Some(Delay::ExponentialBackoff {
            initial_delay: Duration::from_millis(125),
            max_delay: Some(Duration::from_secs(2)),
        }),
    },
    TokioSleep {},
    move || async move {
        some_fallible_operation().await
    },
).await;

Dependencies

~0.3–6.5MB
~27K SLoC