#retry #interval #backoff #delay #random #module

tryumph

A flexible retry library for operations that may fail, with customizable delay strategies for both synchronous and asynchronous code

4 releases

Uses new Rust 2024

new 0.1.3 May 12, 2025
0.1.2 May 11, 2025
0.1.1 May 11, 2025
0.1.0 May 11, 2025

#388 in Algorithms

Download history 385/week @ 2025-05-06

388 downloads per month

MIT license

46KB
743 lines

Tryumph

Crates.io Documentation License CI

A simple, flexible retry library for Rust that handles operations that may fail.

tryumph provides mechanisms for executing operations with customizable retry strategies. It supports both synchronous and asynchronous execution models with various delay strategies for retries.

Features

  • Synchronous retries through the sync module
  • Asynchronous retries through the unsync module
  • Various retry delay strategies:
    • Fixed interval
    • Exponential backoff
    • Immediate (no delay)
    • Random range (requires the random feature)

Installation

Add this to your Cargo.toml:

[dependencies]
tryumph = "0.1.0"

To enable both async and random delay:

[dependencies]
tryumph = { version = "0.1.0", features = ["random"] }

Usage

Synchronous Example

use tryumph::sync::retry;
use tryumph::strategy::Exponential;
use std::time::Duration;

fn main() {
    // Try to get data from a potentially failing API with exponential backoff
    let result = retry(Exponential::from_millis(100).take(3), || {
        // Your operation that may fail
        let response = make_api_request();

        if response.is_success() {
            Ok(response.data)
        } else {
            Err(response.error)
        }
    });

    match result {
        Ok(data) => println!("Successfully retrieved data: {:?}", data),
        Err(e) => println!("Failed after multiple retries: {:?}", e),
    }
}

// Mock functions for example
fn make_api_request() -> Response {
    Response { is_success: true, data: "data", error: "error" }
}
struct Response { is_success: bool, data: &'static str, error: &'static str }
impl Response { fn is_success(&self) -> bool { self.is_success } }

Asynchronous Example

use tryumph::unsync::retry;
use tryumph::strategy::Exponential;

async fn fetch_data() -> Result<String, String> {
    // Try to get data from a potentially failing API
    let result = retry(Exponential::from_millis(100).take(3), || async {
        // Your async operation that may fail
        let response = make_api_request().await;

        if response.is_success() {
            Ok(response.data.to_string())
        } else {
            Err(response.error.to_string())
        }
    }).await;

    match result {
        Ok(data) => {
            println!("Successfully retrieved data: {}", data);
            Ok(data)
        }
        Err(e) => {
            println!("Failed after multiple retries: {}", e);
            Err(e)
        }
    }
}

Using Different Retry Strategies

use tryumph::sync::retry;
use tryumph::strategy::{Fixed, NoDelay};

// Retry with fixed intervals
let result_fixed = retry(Fixed::from_millis(100).take(5), || {
    // Your operation
    Ok::<_, &str>("success")
});

// Retry immediately without delays
let result_nodelay = retry(NoDelay.take(3), || {
    // Your operation
    Ok::<_, &str>("success")
});

Feature Flags

  • random: Enables randomized delay functionality (depends on rand)

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT license, shall be dual licensed as above, without any additional terms or conditions.

Acknowledgments

Dependencies

~2–8.5MB
~61K SLoC