Skip to content

Commit

Permalink
feat: Implement notify support (#19)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuanwo <github@xuanwo.io>

Signed-off-by: Xuanwo <github@xuanwo.io>
  • Loading branch information
Xuanwo authored Sep 17, 2022
1 parent 18f5f3c commit 7d0c192
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 25 deletions.
9 changes: 6 additions & 3 deletions src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ use std::time::Duration;
/// # Examples
///
/// ```no_run
/// use backon::Retryable;
/// use backon::ConstantBackoff;
/// use anyhow::Result;
/// use backon::ConstantBackoff;
/// use backon::Retryable;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
Expand Down
9 changes: 6 additions & 3 deletions src/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ use std::time::Duration;
/// # Examples
///
/// ```no_run
/// use backon::Retryable;
/// use backon::ExponentialBackoff;
/// use anyhow::Result;
/// use backon::ExponentialBackoff;
/// use backon::Retryable;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
Expand Down
21 changes: 14 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
//! Retry with default settings.
//!
//! ```no_run
//! use backon::Retryable;
//! use backon::ExponentialBackoff;
//! use anyhow::Result;
//! use backon::ExponentialBackoff;
//! use backon::Retryable;
//!
//! async fn fetch() -> Result<String> {
//! Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
//! Ok(reqwest::get("https://www.rust-lang.org")
//! .await?
//! .text()
//! .await?)
//! }
//!
//! #[tokio::main]
Expand All @@ -38,19 +41,23 @@
//! Retry with specify retryable error.
//!
//! ```no_run
//! use backon::Retryable;
//! use backon::ExponentialBackoff;
//! use anyhow::Result;
//! use backon::ExponentialBackoff;
//! use backon::Retryable;
//!
//! async fn fetch() -> Result<String> {
//! Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
//! Ok(reqwest::get("https://www.rust-lang.org")
//! .await?
//! .text()
//! .await?)
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let content = fetch
//! .retry(ExponentialBackoff::default())
//! .when(|e| e.to_string() == "retryable").await?;
//! .when(|e| e.to_string() == "retryable")
//! .await?;
//!
//! println!("fetch succeeded: {}", content);
//! Ok(())
Expand Down
74 changes: 62 additions & 12 deletions src/retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use pin_project::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;

use crate::Backoff;

Expand Down Expand Up @@ -38,12 +39,15 @@ use crate::Backoff;
/// # Example
///
/// ```no_run
/// use backon::Retryable;
/// use backon::ExponentialBackoff;
/// use anyhow::Result;
/// use backon::ExponentialBackoff;
/// use backon::Retryable;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
Expand Down Expand Up @@ -76,6 +80,7 @@ where
pub struct Retry<B: Backoff, T, E, Fut: Future<Output = Result<T, E>>, FutureFn: FnMut() -> Fut> {
backoff: B,
retryable: fn(&E) -> bool,
notify: fn(&E, Duration),
future_fn: FutureFn,

#[pin]
Expand All @@ -93,13 +98,16 @@ where
/// # Examples
///
/// ```no_run
/// use backon::Retryable;
/// use backon::Retry;
/// use backon::ExponentialBackoff;
/// use anyhow::Result;
/// use backon::ExponentialBackoff;
/// use backon::Retry;
/// use backon::Retryable;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
Expand All @@ -114,6 +122,7 @@ where
Retry {
backoff,
retryable: |_: &E| true,
notify: |_: &E, _: Duration| {},
future_fn,
state: State::Idle,
}
Expand All @@ -126,18 +135,21 @@ where
/// # Examples
///
/// ```no_run
/// use backon::Retry;
/// use backon::ExponentialBackoff;
/// use anyhow::Result;
/// use backon::ExponentialBackoff;
/// use backon::Retry;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?)
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// let retry = Retry::new(fetch, ExponentialBackoff::default())
/// .when(|e| e.to_string() == "EOF");
/// let retry =
/// Retry::new(fetch, ExponentialBackoff::default()).when(|e| e.to_string() == "EOF");
/// let content = retry.await?;
/// println!("fetch succeeded: {}", content);
///
Expand All @@ -148,6 +160,43 @@ where
self.retryable = retryable;
self
}

/// Set to notify for everything retrying.
///
/// If not specified, this is a no-op.
///
/// # Examples
///
/// ```no_run
/// use anyhow::Result;
/// use backon::ExponentialBackoff;
/// use backon::Retry;
/// use std::time::Duration;
///
/// async fn fetch() -> Result<String> {
/// Ok(reqwest::get("https://www.rust-lang.org")
/// .await?
/// .text()
/// .await?)
/// }
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
/// let retry = Retry::new(fetch, ExponentialBackoff::default()).notify(
/// |err: &anyhow::Error, dur: Duration| {
/// println!("retrying error {:?} with sleeping {:?}", err, dur);
/// },
/// );
/// let content = retry.await?;
/// println!("fetch succeeded: {}", content);
///
/// Ok(())
/// }
/// ```
pub fn notify(mut self, notify: fn(&E, Duration)) -> Self {
self.notify = notify;
self
}
}

/// State maintains internal state of retry.
Expand Down Expand Up @@ -201,6 +250,7 @@ where
match this.backoff.next() {
None => return Poll::Ready(Err(err)),
Some(dur) => {
(this.notify)(&err, dur);
this.state
.set(State::Sleeping(Box::pin(tokio::time::sleep(dur))));
continue;
Expand Down

0 comments on commit 7d0c192

Please sign in to comment.