Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: document custom Sleeper impl #147

Merged
merged 6 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions backon/src/docs/examples/custom_sleeper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Let's implement a custom async Sleeper, say you are using Monoio as your async
runtime, you may want to implement it with `monoio::time::sleep()`. If you want
to implement a custom blocking Sleeper, you will find it pretty similar.

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

/// Sleeper implemented using `monoio::time::sleep()`.
struct MonoioSleeper;

impl Sleeper for MonoioSleeper {
type Sleep = monoio::time::Sleep;

fn sleep(&self, dur: Duration) -> Self::Sleep {
monoio::time::sleep(dur)
}
}
```

Then you can use it like:

```rust
use backon::ExponentialBuilder;
use backon::Retryable;
use anyhow::Result;

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

#[monoio::main(timer_enabled = true)]
async fn main() -> Result<()> {
let content = fetch
.retry(ExponentialBuilder::default())
.sleep(MonoioSleeper)
.await?;

println!("fetch succeeded: {}", content);
Ok(())
}

```
49 changes: 43 additions & 6 deletions backon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,53 @@
//!
//! # Sleep
//!
//! Retry in BackON requires an implementation for sleeping. BackON will accept a [`Sleeper`] to pause for a specified duration.
//! Retry in BackON requires an implementation for sleeping, such an implementation
//! is called a Sleeper, it will implement [`Sleeper`] or [`BlockingSleeper`] depending
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

I try to differentiate "Sleeper" from "`Sleeper`" (quoted with backticks), the former is a general concept, which can be a "`Sleeper`" or "`BlockingSleeper`", while the later is just the async Sleeper trait.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

//! on if it is going to be used in an asynchronous context.
//!
//! BackON employs the following default sleep implementations:
//! ## Default Sleeper
//!
//! - `tokio-sleep`: Utilizes [`TokioSleeper`] within a Tokio context in non-wasm32 environments.
//! - `gloo-timers-sleep`: Utilizes [`GlooTimersSleep`] to pause in wasm32 environments.
//! Currently, BackON has 3 built-in Sleeper implementations for different
//! environments, they are gated under their own features, which are enabled
//! by default:
//!
//! Users CAN provide a custom implementation if they prefer not to use the default options.
//! | `Sleeper` | feature | Environment | Asynchronous |
//! |---------------------|--------------------|-------------|---------------|
//! | [`TokioSleeper`] | tokio-sleep | non-wasm32 | Yes |
//! | [`GlooTimersSleep`] | gloo-timers-sleep | wasm32 | Yes |
//! | [`StdSleeper`] | std-blocking-sleep | all | No |
//!
//! If neither feature is enabled nor a custom implementation is provided, BackON will fallback to an empty sleeper. This will cause a panic in the `debug` profile and do nothing in the `release` profile.
//! ## 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
//!
Expand Down