8个版本

0.3.1 2023年9月14日
0.3.0 2023年9月13日
0.2.4 2023年9月14日
0.2.3 2023年3月14日
0.1.0 2022年6月7日

#5#backoff

Download history 2214/week @ 2024-04-22 2310/week @ 2024-04-29 1132/week @ 2024-05-06 807/week @ 2024-05-13 834/week @ 2024-05-20 1471/week @ 2024-05-27 2615/week @ 2024-06-03 2007/week @ 2024-06-10 2032/week @ 2024-06-17 2351/week @ 2024-06-24 792/week @ 2024-07-01 1821/week @ 2024-07-08 1496/week @ 2024-07-15 1548/week @ 2024-07-22 2359/week @ 2024-07-29 2794/week @ 2024-08-05

8,204 每月下载量

MIT/Apache

38KB
395

futures-retry-policies

一个帮助重试Futures的crate。

use futures_retry_policies::{retry, RetryPolicy};
use std::{ops::ControlFlow, time::Duration};

// 1. Create your retry policy

/// Retries a request n times
pub struct Retries(usize);

// 2. Define how your policy behaves

impl RetryPolicy<Result<(), &'static str>> for Retries {
    fn should_retry(&mut self, result: Result<(), &'static str>) -> ControlFlow<Result<(), &'static str>, Duration> {
        if self.0 > 0 && result.is_err() {
            self.0 -= 1;
            // continue to retry on error
            ControlFlow::Continue(Duration::from_millis(100))
        } else {
            // We've got a success, or we've exhausted our retries, so break
            ControlFlow::Break(result)
        }
    }
}

/// Makes a request, like a HTTP request or gRPC request which you want to retry
async fn make_request() -> Result<(), &'static str>  {
    // make a request
    # static COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
    # if COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst) < 2 { Err("fail") } else { Ok(()) }
}

#[tokio::main]
async fn main() -> Result<(), &'static str> {
    // 3. Await the retry with your policy, a sleep function, and your async function.
    retry(Retries(3), tokio::time::sleep, make_request).await
}

跟踪

添加 tracing 功能,您可以使用 Traced RetryPolicy来自动记录您的重试

Tokio

添加 tokio 功能,您可以使用便捷的tokio重试方法来跳过指定 tokio::time::sleep

您还可以使用 tokio::RetryFutureExt trait来支持在异步函数上直接调用 retry

#[tokio::main]
async fn main() -> Result<(), &'static str> {
    make_request.retry(Retries(3)).await
}

重试策略

此crate对 retry-policies crate 提供了一等支持

use futures_retry_policies::{retry, retry_policies::{ShouldRetry, RetryPolicies}};
use retry_policies::policies::ExponentialBackoff;

enum Error { Retry, DoNotRetry }
impl ShouldRetry for Error {
    fn should_retry(&self, _: u32) -> bool { matches!(self, Error::Retry) }
}
async fn make_request() -> Result<(), Error>  {
    // make a request
    # static COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
    # if COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst) < 2 { Err(Error::Retry) } else { Ok(()) }
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let backoff = ExponentialBackoff::builder().build_with_max_retries(3);
    let policy = RetryPolicies::new(backoff);
    retry(policy, tokio::time::sleep, make_request).await
}

依赖项

~4–11MB
~103K SLoC