13 releases (7 stable)

2.0.0 Sep 17, 2022
1.3.1 Feb 2, 2022
1.3.0 Aug 14, 2021
1.2.1 Apr 24, 2021
0.3.0 Apr 13, 2015

#57 in Concurrency

Download history 24789/week @ 2022-12-01 22631/week @ 2022-12-08 23098/week @ 2022-12-15 13262/week @ 2022-12-22 12480/week @ 2022-12-29 25726/week @ 2023-01-05 25051/week @ 2023-01-12 24644/week @ 2023-01-19 26975/week @ 2023-01-26 21984/week @ 2023-02-02 27662/week @ 2023-02-09 25630/week @ 2023-02-16 29520/week @ 2023-02-23 40388/week @ 2023-03-02 29843/week @ 2023-03-09 26840/week @ 2023-03-16

131,430 downloads per month
Used in 57 crates (37 directly)

MIT license

25KB
478 lines

retry

Build Status

Crate retry provides utilities for retrying operations that can fail.

Documentation

retry has comprehensive documentation available on docs.rs.

retry is released under the MIT license. See LICENSE.


lib.rs:

Crate retry provides utilities for retrying operations that can fail.

Usage

Retry an operation using the [retry] function. [retry] accepts an iterator over [Duration]s and a closure that returns a [Result] (or [OperationResult]; see below). The iterator is used to determine how long to wait after each unsuccessful try and how many times to try before giving up and returning [Result::Err]. The closure determines either the final successful value, or an error value, which can either be returned immediately or used to indicate that the operation should be retried.

Any type that implements [Iterator] with an associated Item type of [Duration] can be used to determine retry behavior, though a few useful implementations are provided in the [delay] module, including a fixed delay and exponential backoff.

# use retry::retry;
# use retry::delay::Fixed;
let mut collection = vec![1, 2, 3].into_iter();

let result = retry(Fixed::from_millis(100), || {
    match collection.next() {
        Some(n) if n == 3 => Ok("n is 3!"),
        Some(_) => Err("n must be 3!"),
        None => Err("n was never 3!"),
    }
});

assert!(result.is_ok());

The [Iterator] API can be used to limit or modify the delay strategy. For example, to limit the number of retries to 1:

# use retry::retry;
# use retry::delay::Fixed;
let mut collection = vec![1, 2, 3].into_iter();

let result = retry(Fixed::from_millis(100).take(1), || {
    match collection.next() {
        Some(n) if n == 3 => Ok("n is 3!"),
        Some(_) => Err("n must be 3!"),
        None => Err("n was never 3!"),
    }
});

assert!(result.is_err());

To deal with fatal errors, return [OperationResult], which is like [Result], but with a third case to distinguish between errors that should cause a retry and errors that should immediately return, halting retry behavior. (Internally, [OperationResult] is always used, and closures passed to [retry] that return plain [Result] are converted into [OperationResult].)

# use retry::retry;
# use retry::delay::Fixed;
use retry::OperationResult;
let mut collection = vec![1, 2].into_iter();
let value = retry(Fixed::from_millis(1), || {
    match collection.next() {
        Some(n) if n == 2 => OperationResult::Ok(n),
        Some(_) => OperationResult::Retry("not 2"),
        None => OperationResult::Err("not found"),
    }
}).unwrap();

assert_eq!(value, 2);

If your operation needs to know how many times it's been tried, use the [retry_with_index] function. This works the same as [retry], but passes the number of the current try to the closure as an argument.

# use retry::retry_with_index;
# use retry::delay::Fixed;
# use retry::OperationResult;
let mut collection = vec![1, 2, 3, 4, 5].into_iter();

let result = retry_with_index(Fixed::from_millis(100), |current_try| {
    if current_try > 3 {
        return OperationResult::Err("did not succeed within 3 tries");
    }

    match collection.next() {
        Some(n) if n == 5 => OperationResult::Ok("n is 5!"),
        Some(_) => OperationResult::Retry("n must be 5!"),
        None => OperationResult::Retry("n was never 5!"),
    }
});

assert!(result.is_err());

Features

  • random: offer some random delay utilities (on by default)

Dependencies

~73KB