Crate backon

Source
Expand description

Build Status Latest Version

BackON

Make retry like a built-in feature provided by Rust.

  • Simple: Just like a built-in feature: your_fn.retry(ExponentialBuilder::default()).await.
  • Flexible: Supports both blocking and async functions.
  • Powerful: Allows control over retry behavior such as when and notify.
  • Customizable: Supports custom retry strategies like exponential, constant, etc.

§Backoff

Retry in BackON requires a backoff strategy. BackON will accept a BackoffBuilder which will generate a new Backoff for each retry.

BackON provides several backoff implementations with reasonable defaults:

§Sleep

Retry in BackON requires an implementation for sleeping, such an implementation is called a Sleeper, it will implement Sleeper or BlockingSleeper depending on if it is going to be used in an asynchronous context.

§Default Sleeper

Currently, BackON has 3 built-in Sleeper implementations for different environments, they are gated under their own features, which are enabled by default:

SleeperfeatureEnvironmentAsynchronous
TokioSleepertokio-sleepnon-wasm32Yes
[GlooTimersSleep]gloo-timers-sleepwasm32Yes
StdSleeperstd-blocking-sleepallNo

§Custom Sleeper

If you do not want to use the built-in Sleeper, you CAN provide a custom implementation, let’s implement an asynchronous dummy Sleeper that does not sleep at all. You will find it pretty similar when you implement a blocking one.

use std::time::Duration;
use backon::Sleeper;

/// A dummy `Sleeper` impl that prints then becomes ready!
struct DummySleeper;

impl Sleeper for DummySleeper {
    type Sleep = std::future::Ready<()>;

    fn sleep(&self, dur: Duration) -> Self::Sleep {
        println!("Hello from DummySleeper!");
        std::future::ready(())
    }
}

§The empty Sleeper

If neither feature is enabled nor a custom implementation is provided, BackON will fallback to the empty sleeper, in which case, a compile-time error that PleaseEnableAFeatureOrProvideACustomSleeper needs to implement Sleeper or BlockingSleeper will be raised to remind you to choose or bring a real Sleeper implementation.

§Retry

For additional examples, please visit docs::examples.

§Retry an async function

use anyhow::Result;
use backon::ExponentialBuilder;
use backon::Retryable;
use core::time::Duration;

async fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

#[tokio::main]
async fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, default to tokio::time::sleep if `tokio-sleep` has been enabled.
        .sleep(tokio::time::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .await?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

§Retry a blocking function

use anyhow::Result;
use backon::BlockingRetryable;
use backon::ExponentialBuilder;
use core::time::Duration;

fn fetch() -> Result<String> {
    Ok("hello, world!".to_string())
}

fn main() -> Result<()> {
    let content = fetch
        // Retry with exponential backoff
        .retry(ExponentialBuilder::default())
        // Sleep implementation, default to std::thread::sleep if `std-blocking-sleep` has been enabled.
        .sleep(std::thread::sleep)
        // When to retry
        .when(|e| e.to_string() == "EOF")
        // Notify when retrying
        .notify(|err: &anyhow::Error, dur: Duration| {
            println!("retrying {:?} after {:?}", err, dur);
        })
        .call()?;
    println!("fetch succeeded: {}", content);

    Ok(())
}

Re-exports§

  • pub use constant::ConstantBackoff;
  • pub use fibonacci::FibonacciBackoff;
  • pub use exponential::ExponentialBackoff;

Modules§

Structs§

Traits§

Type Aliases§

  • The default implementation of Sleeper while feature std-blocking-sleep enabled.
  • The default implementation of Sleeper while feature tokio-sleep enabled.