### Register backon example modules Source: https://docs.rs/backon/1.6.0/src/backon/docs/examples/mod.rs.html Defines the module structure for backon examples by including external markdown documentation files. ```rust //! Examples of using backon. #[doc = include_str!("basic.md")] pub mod basic {} #[doc = include_str!("closure.md")] pub mod closure {} #[doc = include_str!("inside_mut_self.md")] pub mod inside_mut_self {} #[doc = include_str!("sqlx.md")] pub mod sqlx {} #[doc = include_str!("with_args.md")] pub mod with_args {} #[doc = include_str!("with_mut_self.md")] pub mod with_mut_self {} #[doc = include_str!("with_self.md")] pub mod with_self {} #[doc = include_str!("with_specific_error.md")] pub mod with_specific_error {} #[doc = include_str!("retry_after.md")] pub mod retry_after {} ``` -------------------------------- ### Define backon documentation module Source: https://docs.rs/backon/1.6.0/src/backon/docs/mod.rs.html Exposes the examples module for crate documentation. ```rust //! Docs for the backon crate, like [`examples`]. pub mod examples; ``` -------------------------------- ### BlockingRetryable Usage Examples Source: https://docs.rs/backon/1.6.0/backon/trait.BlockingRetryable.html?search=u32+-%3E+bool Examples showing how to define functions or closures that can be used with the retry mechanism. ```rust fn fetch() -> Result { Ok("hello, world!".to_string()) } ``` ```rust || { Ok("hello, world!".to_string()) } ``` -------------------------------- ### Implementing Blocking Retry Source: https://docs.rs/backon/1.6.0/backon/trait.BlockingRetryable.html?search=u32+-%3E+bool A complete example demonstrating how to use the retry method with an ExponentialBuilder. ```rust use anyhow::Result; use backon::BlockingRetryable; use backon::ExponentialBuilder; fn fetch() -> Result { Ok("hello, world!".to_string()) } fn main() -> Result<()> { let content = fetch.retry(ExponentialBuilder::default()).call()?; println!("fetch succeeded: {}", content); Ok(()) } ``` -------------------------------- ### Default Sleeper Test Setup Source: https://docs.rs/backon/1.6.0/src/backon/retry.rs.html?search=std%3A%3Avec Imports and setup for testing the default sleeper implementation. ```rust extern crate alloc; use alloc::string::ToString; use alloc::vec; use alloc::vec::Vec; use core::time::Duration; use tokio::sync::Mutex; ``` -------------------------------- ### Configure Retry Conditions with when Source: https://docs.rs/backon/1.6.0/backon/struct.RetryWithContext.html Example demonstrating how to use the when method to specify retry conditions based on the error. ```rust use anyhow::Result; use backon::ExponentialBuilder; use backon::Retryable; async fn fetch() -> Result { Ok(reqwest::get("https://www.rust-lang.org") .await? .text() .await?) } #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { let content = fetch .retry(ExponentialBuilder::default()) .when(|e| e.to_string() == "EOF") .await?; println!("fetch succeeded: {}", content); Ok(()) } ``` -------------------------------- ### Retryable Usage Examples Source: https://docs.rs/backon/1.6.0/backon/trait.Retryable.html Examples of functions and closures that can utilize the retry functionality. ```rust async fn fetch() -> Result { Ok(reqwest::get("https://www.rust-lang.org").await?.text().await?) } ``` ```rust || async { let x = reqwest::get("https://www.rust-lang.org") .await? .text() .await?; Err(anyhow::anyhow!(x)) } ``` -------------------------------- ### Retry with FibonacciBackoff Source: https://docs.rs/backon/1.6.0/backon/struct.FibonacciBuilder.html?search= Example demonstrating how to use FibonacciBuilder to configure a retry strategy for an asynchronous function. ```rust use anyhow::Result; use backon::FibonacciBuilder; use backon::Retryable; async fn fetch() -> Result { Ok(reqwest::get("https://www.rust-lang.org") .await? .text() .await?) } #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { let content = fetch.retry(FibonacciBuilder::default()).await?; println!("fetch succeeded: {}", content); Ok(()) } ``` -------------------------------- ### Configure Retry Notifications with notify Source: https://docs.rs/backon/1.6.0/backon/struct.RetryWithContext.html Example demonstrating how to use the notify method to execute a callback during retry attempts. ```rust use core::time::Duration; use anyhow::Result; use backon::ExponentialBuilder; use backon::Retryable; async fn fetch() -> Result { Ok(reqwest::get("https://www.rust-lang.org") .await? .text() .await?) } #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { let content = fetch .retry(ExponentialBuilder::default()) .notify(|err: &anyhow::Error, dur: Duration| { println!("retrying error {:?} with sleeping {:?}", err, dur); }) .await?; println!("fetch succeeded: {}", content); Ok(()) ``` -------------------------------- ### Setting retry conditions Source: https://docs.rs/backon/1.6.0/src/backon/retry.rs.html?search=u32+-%3E+bool Example of configuring retry conditions using the retryable method. ```rust use anyhow::Result; use backon::ExponentialBuilder; use backon::Retryable; async fn fetch() -> Result { ``` -------------------------------- ### BackoffBuilder Test Implementation Source: https://docs.rs/backon/1.6.0/src/backon/backoff/api.rs.html Example usage of BackoffBuilder with various implementations in a test context. ```rust #[cfg(test)] mod tests { use super::*; use crate::ConstantBuilder; use crate::ExponentialBuilder; use crate::FibonacciBuilder; fn test_fn_builder(b: impl BackoffBuilder) { let _ = b.build(); } #[test] fn test_backoff_builder() { test_fn_builder([Duration::from_secs(1)].into_iter()); // Just for test if user can keep using &XxxBuilder. #[allow(clippy::needless_borrows_for_generic_args)] { test_fn_builder(&ConstantBuilder::default()); test_fn_builder(&FibonacciBuilder::default()); test_fn_builder(&ExponentialBuilder::default()); } } } ``` -------------------------------- ### Compiler Error Example Source: https://docs.rs/backon/1.6.0/backon/trait.RetryableWithContext.html?search= An example of a compiler error encountered when attempting to capture variables in a closure without context support. ```text error: captured variable cannot escape `FnMut` closure body --> src/retry.rs:404:27 | 400 | let mut test = Test; | -------- variable defined here ... 404 | let result = { || async { test.hello().await } } | - ^^^^^^^^----^^^^^^^^^^^^^^^^ | | | | | | | variable captured here | | returns an `async` block that contains a reference to a captured variable, which then escapes the closure body | inferred to be a `FnMut` closure | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape ``` -------------------------------- ### Retry with ConstantBuilder Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html Example demonstrating how to use ConstantBuilder with the Retryable trait to perform an asynchronous operation with constant backoff. ```rust use anyhow::Result; use backon::ConstantBuilder; use backon::Retryable; async fn fetch() -> Result { Ok(reqwest::get("https://www.rust-lang.org") .await? .text() .await?) } #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { let content = fetch.retry(ConstantBuilder::default()).await?; println!("fetch succeeded: {}", content); Ok(()) } ``` -------------------------------- ### Conditional Retry Logic Source: https://docs.rs/backon/1.6.0/src/backon/blocking_retry.rs.html?search=u32+-%3E+bool Examples demonstrating how to use the .when() method to filter which errors trigger a retry. ```rust fn test_retry_with_not_retryable_error() -> anyhow::Result<()> { let error_times = Mutex::new(0); let f = || { let mut x = error_times.lock(); *x += 1; Err::<(), anyhow::Error>(anyhow::anyhow!("not retryable")) }; let backoff = ExponentialBuilder::default().with_min_delay(Duration::from_millis(1)); let result = f .retry(backoff) // Only retry If error message is `retryable` .when(|e| e.to_string() == "retryable") .call(); assert!(result.is_err()); assert_eq!("not retryable", result.unwrap_err().to_string()); // `f` always returns error "not retryable", so it should be executed // only once. assert_eq!(*error_times.lock(), 1); Ok(()) } ``` ```rust fn test_retry_with_retryable_error() -> anyhow::Result<()> { let error_times = Mutex::new(0); let f = || { // println!("I have been called!"); let mut x = error_times.lock(); *x += 1; Err::<(), anyhow::Error>(anyhow::anyhow!("retryable")) }; let backoff = ExponentialBuilder::default().with_min_delay(Duration::from_millis(1)); let result = f .retry(backoff) // Only retry If error message is `retryable` .when(|e| e.to_string() == "retryable") .call(); assert!(result.is_err()); assert_eq!("retryable", result.unwrap_err().to_string()); ``` -------------------------------- ### Test Exponential Max Delay Manual Configuration Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html?search= Tests manual struct initialization for ExponentialBuilder. ```rust #[test] fn test_exponential_max_delay_without_default_1() { let mut exp = ExponentialBuilder { jitter: false, seed: Some(0x2fdb0020ffc7722b), factor: 10_000_000_000_f32, min_delay: Duration::from_secs(1), max_delay: None, max_times: None, total_delay: None, } .build(); assert_eq!(Some(Duration::from_secs(1)), exp.next()); assert_eq!(Some(Duration::from_secs(10_000_000_000)), exp.next()); assert_eq!(Some(Duration::MAX), exp.next()); assert_eq!(Some(Duration::MAX), exp.next()); } ``` ```rust #[test] fn test_exponential_max_delay_without_default_2() { let mut exp = ExponentialBuilder { jitter: true, seed: Some(0x2fdb0020ffc7722b), factor: 10_000_000_000_f32, min_delay: Duration::from_secs(10_000_000_000), max_delay: None, max_times: Some(2), total_delay: None, } .build(); let v = exp.next().expect("value must valid"); assert!(v >= Duration::from_secs(10_000_000_000), "current: {v:?}"); assert!(v < Duration::from_secs(20_000_000_000), "current: {v:?}"); assert_eq!(Some(Duration::MAX), exp.next()); assert_eq!(None, exp.next()); } ``` ```rust #[test] fn test_exponential_max_delay_without_default_3() { let mut exp = ExponentialBuilder { jitter: false, seed: Some(0x2fdb0020ffc7722b), factor: 10_000_000_000_f32, min_delay: Duration::from_secs(10_000_000_000), max_delay: Some(Duration::from_secs(60_000_000_000)), max_times: Some(3), total_delay: None, } .build(); ``` -------------------------------- ### Define a retryable closure Source: https://docs.rs/backon/1.6.0/src/backon/blocking_retry.rs.html?search= Example of a closure that can be used with the retry mechanism. ```rust || { Ok("hello, world!".to_string()) } ``` -------------------------------- ### Basic Retry Usage Source: https://docs.rs/backon/1.6.0/src/backon/retry.rs.html Demonstrates a simple retry execution using an exponential backoff builder. ```rust async fn always_error() -> anyhow::Result<()> { Err(anyhow::anyhow!("test_query meets error")) } #[test] async fn test_retry() { let result = always_error .retry(ExponentialBuilder::default().with_min_delay(Duration::from_millis(1))) .await; assert!(result.is_err()); assert_eq!("test_query meets error", result.unwrap_err().to_string()); } ``` -------------------------------- ### build() Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html?search=std%3A%3Avec Constructs a new backoff instance using the builder. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff using the builder. ### Returns - **Self::Backoff** - The constructed backoff instance. ``` -------------------------------- ### Define a retryable function Source: https://docs.rs/backon/1.6.0/src/backon/blocking_retry.rs.html?search= Example of a simple function that can be used with the retry mechanism. ```rust fn fetch() -> Result { Ok("hello, world!".to_string()) } ``` -------------------------------- ### fn default() -> Self Source: https://docs.rs/backon/1.6.0/backon/struct.FibonacciBuilder.html?search=std%3A%3Avec Returns the default configuration for the FibonacciBuilder. ```APIDOC ## fn default() -> Self ### Description Returns the default value for the FibonacciBuilder type. ``` -------------------------------- ### ExponentialBuilder::default Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=u32+-%3E+bool Creates a new ExponentialBuilder with default settings. ```APIDOC ## fn default() -> Self ### Description Returns the default value for the ExponentialBuilder type. ``` -------------------------------- ### Defining a ConstantBuilder test constant Source: https://docs.rs/backon/1.6.0/src/backon/backoff/constant.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to instantiate a ConstantBuilder with custom parameters in a test environment. ```rust const TEST_BUILDER: ConstantBuilder = ConstantBuilder::new() .with_delay(Duration::from_secs(2)) ``` -------------------------------- ### ConstantBuilder::default Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html?search=u32+-%3E+bool Creates a new ConstantBuilder with default settings. ```APIDOC ## fn default() -> Self ### Description Returns the default value for the ConstantBuilder type. ``` -------------------------------- ### fn build(self) -> Self::Backoff Source: https://docs.rs/backon/1.6.0/backon/trait.BackoffBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Constructs a new backoff instance using the builder. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff instance using the builder. This is the primary method for initializing a backoff strategy. ### Signature `fn build(self) -> Self::Backoff` ### Returns - **Self::Backoff** - The associated backoff type defined by the specific implementation of the builder. ``` -------------------------------- ### fn build(self) -> Self::Backoff Source: https://docs.rs/backon/1.6.0/backon/trait.BackoffBuilder.html?search=std%3A%3Avec Constructs a new backoff instance using the builder. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff instance using the builder. ### Signature `fn build(self) -> Self::Backoff` ### Returns - **Self::Backoff** - The associated backoff instance created by the builder. ``` -------------------------------- ### fn build(self) -> Self::Backoff Source: https://docs.rs/backon/1.6.0/backon/trait.BackoffBuilder.html?search= Constructs a new backoff instance using the builder. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff instance using the builder. This is a required method for any type implementing the BackoffBuilder trait. ### Signature `fn build(self) -> Self::Backoff` ### Returns - **Self::Backoff** - The associated backoff type defined by the implementation. ``` -------------------------------- ### ExponentialBuilder Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E A builder for configuring exponential backoff strategies. ```APIDOC ## ExponentialBuilder ### Description ExponentialBuilder is used to construct an ExponentialBackoff that offers delays with exponential retries. It provides methods to customize the retry behavior. ### Methods - **new()** - Creates a new `ExponentialBuilder` with default values (jitter: false, factor: 2, min_delay: 1s, max_delay: 60s, max_times: 3). - **with_jitter()** - Enables random jitter within `(0, current_delay)`. - **with_jitter_seed(seed: u64)** - Sets the seed for the jitter random number generator. - **with_factor(factor: f32)** - Sets the exponential factor for the backoff. - **with_min_delay(min_delay: Duration)** - Sets the minimum delay duration. - **with_max_delay(max_delay: Duration)** - Sets the maximum delay duration. - **without_max_delay()** - Removes the maximum delay constraint. - **with_max_times(max_times: usize)** - Sets the maximum number of retry attempts. - **without_max_times()** - Removes the maximum retry attempts constraint. - **with_total_delay(total_delay: Option)** - Sets a cumulative total delay limit for the backoff. ### Usage Example ```rust use backon::ExponentialBuilder; use backon::Retryable; let builder = ExponentialBuilder::default() .with_jitter() .with_max_times(5); // Use with a retryable function // let result = my_func.retry(builder).await?; ``` ``` -------------------------------- ### ConstantBuilder Methods Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html Methods available for configuring a ConstantBuilder instance. ```APIDOC ## pub const fn new() -> Self ### Description Creates a new `ConstantBuilder` with default values (1s delay, 3 max retries). ## pub const fn with_delay(self, delay: Duration) -> Self ### Description Sets the delay duration for the backoff. ## pub const fn with_max_times(self, max_times: usize) -> Self ### Description Sets the maximum number of attempts to be made. ## pub const fn with_jitter(self) -> Self ### Description Enables jitter for the backoff to prevent thundering herd problems. ## pub fn with_jitter_seed(self, seed: u64) -> Self ### Description Sets the seed value for the jitter random number generator. ## pub const fn without_max_times(self) -> Self ### Description Configures the backoff to have no maximum number of attempts. ``` -------------------------------- ### ExponentialBuilder Methods Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=std%3A%3Avec Methods available for configuring an ExponentialBuilder instance. ```APIDOC ## ExponentialBuilder Methods ### new() Creates a new `ExponentialBuilder` with default values (jitter: false, factor: 2, min_delay: 1s, max_delay: 60s, max_times: 3). ### with_jitter(self) -> Self Enables jitter for the backoff, adding a random value within (0, current_delay). ### with_jitter_seed(self, seed: u64) -> Self Sets the seed for the jitter random number generator. ### with_factor(self, factor: f32) -> Self Sets the exponential factor for the backoff. ### with_min_delay(self, min_delay: Duration) -> Self Sets the minimum delay duration. ### with_max_delay(self, max_delay: Duration) -> Self Sets the maximum delay duration. ### without_max_delay(self) -> Self Removes the maximum delay constraint. ### with_max_times(self, max_times: usize) -> Self Sets the maximum number of retry attempts. ### without_max_times(self) -> Self Removes the maximum retry attempts constraint. ### with_total_delay(self, total_delay: Option) -> Self Sets the total cumulative delay limit for the backoff. ``` -------------------------------- ### ExponentialBuilder Methods Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Methods available for configuring an ExponentialBuilder instance. ```APIDOC ## ExponentialBuilder Methods ### new() Creates a new `ExponentialBuilder` with default values. ### with_jitter(self) -> Self Enables jitter for the backoff, adding a random delay within (0, current_delay). ### with_jitter_seed(self, seed: u64) -> Self Sets the seed value for the jitter random number generator. ### with_factor(self, factor: f32) -> Self Sets the exponential factor for the backoff. ### with_min_delay(self, min_delay: Duration) -> Self Sets the minimum delay duration. ### with_max_delay(self, max_delay: Duration) -> Self Sets the maximum delay duration. ### without_max_delay(self) -> Self Removes the maximum delay constraint. ### with_max_times(self, max_times: usize) -> Self Sets the maximum number of retry attempts. ### without_max_times(self) -> Self Removes the maximum retry attempts constraint. ### with_total_delay(self, total_delay: Option) -> Self Sets the total cumulative delay limit for the backoff. ``` -------------------------------- ### ExponentialBuilder Configuration Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html The ExponentialBuilder allows for the configuration of exponential backoff parameters. It provides methods to set jitter, factors, minimum/maximum delays, and maximum retry attempts. ```APIDOC ## ExponentialBuilder ### Description Constructs an `ExponentialBackoff` strategy with configurable parameters for exponential retry delays. ### Methods - **new()** - Creates a new `ExponentialBuilder` with default values (jitter: false, factor: 2.0, min_delay: 1s, max_delay: 60s, max_times: 3). - **with_jitter()** - Enables random jitter within (0, current_delay). - **with_jitter_seed(seed: u64)** - Sets a seed for the jitter random number generator. - **with_factor(factor: f32)** - Sets the exponential growth factor. - **with_min_delay(min_delay: Duration)** - Sets the minimum delay duration. - **with_max_delay(max_delay: Duration)** - Sets the maximum delay duration. - **without_max_delay()** - Removes the maximum delay constraint. - **with_max_times(max_times: usize)** - Sets the maximum number of retry attempts. - **without_max_times()** - Removes the maximum retry attempts constraint. - **with_total_delay(total_delay: Option)** - Sets a cumulative limit for all sleep durations. ``` -------------------------------- ### Retry with Exponential Backoff and Custom Sleep Source: https://docs.rs/backon/1.6.0/src/backon/retry.rs.html?search=u32+-%3E+bool Demonstrates configuring a retry strategy with an exponential builder and a custom sleep function. ```rust async fn test_retry_with_sleep() { let result = always_error .retry(ExponentialBuilder::default().with_min_delay(Duration::from_millis(1))) .sleep(|_| ready(())) .await; assert!(result.is_err()); assert_eq!("test_query meets error", result.unwrap_err().to_string()); } ``` -------------------------------- ### BlockingRetryWithContext Configuration Methods Source: https://docs.rs/backon/1.6.0/backon/struct.BlockingRetryWithContext.html?search= Methods for configuring the retry behavior, including context, sleeper, retry conditions, and notifications. ```rust pub fn context( self, context: Ctx, ) -> BlockingRetryWithContext ``` ```rust pub fn sleep( self, sleep_fn: SN, ) -> BlockingRetryWithContext ``` ```rust pub fn when bool>( self, retryable: RN, ) -> BlockingRetryWithContext ``` ```rust pub fn notify( self, notify: NN, ) -> BlockingRetryWithContext ``` -------------------------------- ### Testing Non-Retryable Errors with Context Source: https://docs.rs/backon/1.6.0/src/backon/blocking_retry_with_context.rs.html Demonstrates how to configure a retry strategy that terminates immediately when a non-retryable error occurs. ```rust #[test] fn test_retry_with_not_retryable_error() -> Result<()> { let error_times = Mutex::new(0); let test = Test; let backoff = ExponentialBuilder::default().with_min_delay(Duration::from_millis(1)); let (_, result) = { |mut v: Test| { let mut x = error_times.lock(); *x += 1; let res = v.hello(); (v, res) } } .retry(backoff) .context(test) // Only retry If error message is `retryable` .when(|e| e.to_string() == "retryable") .call(); assert!(result.is_err()); assert_eq!("not retryable", result.unwrap_err().to_string()); // `f` always returns error "not retryable", so it should be executed // only once. assert_eq!(*error_times.lock(), 1); Ok(()) } ``` -------------------------------- ### Test Exponential Min Delay Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html Verifies that the builder respects the minimum delay configuration. ```rust #[test] fn test_exponential_min_delay() { let mut exp = ExponentialBuilder::default() .with_min_delay(Duration::from_millis(500)) .build(); assert_eq!(Some(Duration::from_millis(500)), exp.next()); assert_eq!(Some(Duration::from_secs(1)), exp.next()); assert_eq!(Some(Duration::from_secs(2)), exp.next()); assert_eq!(None, exp.next()); } ``` -------------------------------- ### Module Exports and Configuration Source: https://docs.rs/backon/1.6.0/src/backon/backoff/mod.rs.html Exposes backoff strategies and defines a random seed for no_std environments. ```rust 1mod api; 2pub use api::*; 3 4mod constant; 5pub use constant::ConstantBackoff; 6pub use constant::ConstantBuilder; 7 8mod fibonacci; 9pub use fibonacci::FibonacciBackoff; 10pub use fibonacci::FibonacciBuilder; 11 12mod exponential; 13pub use exponential::ExponentialBackoff; 14pub use exponential::ExponentialBuilder; 15 16// Random seed value for no_std (the value is "backon" in hex) 17#[cfg(not(feature = "std"))] 18const RANDOM_SEED: u64 = 0x6261636b6f6e; ``` -------------------------------- ### ExponentialBuilder::default Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Returns the default configuration for the ExponentialBuilder. ```APIDOC ## fn default() -> Self ### Description Returns the default value for the ExponentialBuilder. ### Returns - **Self** - A new instance of ExponentialBuilder with default settings. ``` -------------------------------- ### Test FnMut with when and notify hooks Source: https://docs.rs/backon/1.6.0/src/backon/blocking_retry.rs.html?search= Demonstrates using the retry builder with when and notify closures to track execution attempts in a blocking context. ```rust #[test] fn test_fn_mut_when_and_notify() -> anyhow::Result<()> { let mut calls_retryable: Vec<()> = vec![]; let mut calls_notify: Vec<()> = vec![]; let f = || Err::<(), anyhow::Error>(anyhow::anyhow!("retryable")); let backoff = ExponentialBuilder::default().with_min_delay(Duration::from_millis(1)); let result = f .retry(backoff) .when(|_| { calls_retryable.push(()); true }) .notify(|_, _| { calls_notify.push(()); }) .call(); assert!(result.is_err()); assert_eq!("retryable", result.unwrap_err().to_string()); // `f` always returns error "retryable", so it should be executed // 4 times (retry 3 times). assert_eq!(calls_retryable.len(), 4); assert_eq!(calls_notify.len(), 3); Ok(()) } ``` -------------------------------- ### Test ConstantBuilder with Custom Delay Source: https://docs.rs/backon/1.6.0/src/backon/backoff/constant.rs.html Demonstrates configuring a specific delay duration for the backoff strategy. ```rust #[test] fn test_constant_with_delay() { let mut it = ConstantBuilder::default() .with_delay(Duration::from_secs(2)) .build(); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(None, it.next()); } ``` -------------------------------- ### ConstantBuilder::new Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html?search= Creates a new ConstantBuilder instance with default values (1s delay, 3 max retries). ```APIDOC ## pub const fn new() -> Self ### Description Creates a new `ConstantBuilder` with default values. ``` -------------------------------- ### FibonacciBuilder Methods Source: https://docs.rs/backon/1.6.0/backon/struct.FibonacciBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Methods available for configuring a FibonacciBuilder instance. ```APIDOC ## FibonacciBuilder Methods ### new() Creates a new `FibonacciBuilder` with default values. ### with_jitter() Enables jitter for the backoff, adding a random delay between `(0, current_delay)`. ### with_jitter_seed(seed: u64) Sets the seed value for the jitter random number generator. ### with_min_delay(min_delay: Duration) Sets the minimum delay for the backoff. ### with_max_delay(max_delay: Duration) Sets the maximum delay for the backoff. ### without_max_delay() Removes the maximum delay constraint. ### with_max_times(max_times: usize) Sets the maximum number of retry attempts. ### without_max_times() Removes the maximum number of attempts constraint. ``` -------------------------------- ### FibonacciBackoff Unit Tests Source: https://docs.rs/backon/1.6.0/src/backon/backoff/fibonacci.rs.html Various test cases demonstrating default behavior, jitter, min/max delay constraints, and edge cases. ```rust #[cfg(test)] mod tests { use core::time::Duration; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::wasm_bindgen_test as test; use super::*; const TEST_BUILDER: FibonacciBuilder = FibonacciBuilder::new() .with_jitter() .with_min_delay(Duration::from_secs(2)) .with_max_delay(Duration::from_secs(30)) .with_max_times(5); #[test] fn test_fibonacci_default() { let mut fib = FibonacciBuilder::default().build(); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(None, fib.next()); } #[test] fn test_fibonacci_jitter() { let mut fib = FibonacciBuilder::default().with_jitter().build(); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(1), "current: {v:?}"); assert!(v < Duration::from_secs(2), "current: {v:?}"); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(1), "current: {v:?}"); assert!(v < Duration::from_secs(2), "current: {v:?}"); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(2), "current: {v:?}"); assert!(v < Duration::from_secs(3), "current: {v:?}"); assert_eq!(None, fib.next()); } #[test] fn test_fibonacci_min_delay() { let mut fib = FibonacciBuilder::default() .with_min_delay(Duration::from_millis(500)) .build(); assert_eq!(Some(Duration::from_millis(500)), fib.next()); assert_eq!(Some(Duration::from_millis(500)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(None, fib.next()); } #[test] fn test_fibonacci_max_delay() { let mut fib = FibonacciBuilder::default() .with_max_times(4) .with_max_delay(Duration::from_secs(2)) .build(); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(None, fib.next()); } #[test] fn test_fibonacci_no_max_delay() { let mut fib = FibonacciBuilder::default() .with_max_times(4) .with_min_delay(Duration::from_secs(10_000_000_000_000_000_000)) .without_max_delay() .build(); assert_eq!( Some(Duration::from_secs(10_000_000_000_000_000_000)), fib.next() ); assert_eq!( Some(Duration::from_secs(10_000_000_000_000_000_000)), fib.next() ); } } ``` -------------------------------- ### Test ConstantBuilder Default Configuration Source: https://docs.rs/backon/1.6.0/src/backon/backoff/constant.rs.html Verifies the default behavior of the ConstantBuilder, which defaults to a 1-second delay. ```rust #[test] fn test_constant_default() { let mut it = ConstantBuilder::default().build(); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(None, it.next()); } ``` -------------------------------- ### Test ConstantBuilder configurations Source: https://docs.rs/backon/1.6.0/src/backon/backoff/constant.rs.html?search=u32+-%3E+bool Unit tests verifying the behavior of ConstantBuilder with different parameters. ```rust #[test] fn test_constant_default() { let mut it = ConstantBuilder::default().build(); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(None, it.next()); } ``` ```rust #[test] fn test_constant_with_delay() { let mut it = ConstantBuilder::default() .with_delay(Duration::from_secs(2)) .build(); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(Some(Duration::from_secs(2)), it.next()); assert_eq!(None, it.next()); } ``` ```rust #[test] fn test_constant_with_times() { let mut it = ConstantBuilder::default().with_max_times(1).build(); assert_eq!(Some(Duration::from_secs(1)), it.next()); assert_eq!(None, it.next()); } ``` ```rust #[test] fn test_constant_with_jitter() { let mut it = ConstantBuilder::default().with_jitter().build(); let dur = it.next().unwrap(); fastrand::seed(7); assert!(dur > Duration::from_secs(1)); } ``` ```rust #[test] fn test_constant_without_max_times() { let mut it = ConstantBuilder::default().without_max_times().build(); for _ in 0..10_000 { assert_eq!(Some(Duration::from_secs(1)), it.next()); } } ``` ```rust #[allow(clippy::assertions_on_constants)] #[test] fn test_constant_const_builder() { assert_eq!(TEST_BUILDER.delay, Duration::from_secs(2)); assert_eq!(TEST_BUILDER.max_times, Some(5)); assert!(TEST_BUILDER.jitter); } ``` -------------------------------- ### ConstantBuilder::build Source: https://docs.rs/backon/1.6.0/backon/struct.ConstantBuilder.html?search=u32+-%3E+bool Constructs a new ConstantBackoff instance using the current builder configuration. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff instance using the builder configuration. ### Returns - **Self::Backoff** - The configured ConstantBackoff instance. ``` -------------------------------- ### ExponentialBuilder::build Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Constructs a new ExponentialBackoff instance using the current builder configuration. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff using the builder configuration. ### Returns - **Self::Backoff** - The configured ExponentialBackoff instance. ``` -------------------------------- ### ExponentialBuilder::build Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=u32+-%3E+bool Constructs a new ExponentialBackoff instance using the current builder configuration. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff using the builder. ### Returns - **Self::Backoff** (ExponentialBackoff) - The configured backoff instance. ``` -------------------------------- ### Exponential Backoff Unit Tests Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html Test cases demonstrating default behavior, custom factors, and jitter application. ```rust #[test] fn test_exponential_default() { let mut exp = ExponentialBuilder::default().build(); assert_eq!(Some(Duration::from_secs(1)), exp.next()); assert_eq!(Some(Duration::from_secs(2)), exp.next()); assert_eq!(Some(Duration::from_secs(4)), exp.next()); assert_eq!(None, exp.next()); } ``` ```rust #[test] fn test_exponential_factor() { let mut exp = ExponentialBuilder::default().with_factor(1.5).build(); assert_eq!(Some(Duration::from_secs_f32(1.0)), exp.next()); assert_eq!(Some(Duration::from_secs_f32(1.5)), exp.next()); assert_eq!(Some(Duration::from_secs_f32(2.25)), exp.next()); assert_eq!(None, exp.next()); } ``` ```rust #[test] fn test_exponential_jitter() { let mut exp = ExponentialBuilder::default().with_jitter().build(); let v = exp.next().expect("value must valid"); assert!(v >= Duration::from_secs(1), "current: {v:?}"); assert!(v < Duration::from_secs(2), "current: {v:?}"); ``` -------------------------------- ### Exporting Backoff Strategies in Rust Source: https://docs.rs/backon/1.6.0/src/backon/backoff/mod.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Module exports for backoff strategies and a constant seed for no_std environments. ```rust mod api; pub use api::*; mod constant; pub use constant::ConstantBackoff; pub use constant::ConstantBuilder; mod fibonacci; pub use fibonacci::FibonacciBackoff; pub use fibonacci::FibonacciBuilder; mod exponential; pub use exponential::ExponentialBackoff; pub use exponential::ExponentialBuilder; // Random seed value for no_std (the value is "backon" in hex) #[cfg(not(feature = "std"))] const RANDOM_SEED: u64 = 0x6261636b6f6e; ``` -------------------------------- ### Test Exponential Max Delay Without Default 1 Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html Verifies manual struct initialization for ExponentialBuilder without default settings. ```rust #[test] fn test_exponential_max_delay_without_default_1() { let mut exp = ExponentialBuilder { jitter: false, seed: Some(0x2fdb0020ffc7722b), factor: 10_000_000_000_f32, min_delay: Duration::from_secs(1), max_delay: None, max_times: None, total_delay: None, } .build(); assert_eq!(Some(Duration::from_secs(1)), exp.next()); assert_eq!(Some(Duration::from_secs(10_000_000_000)), exp.next()); assert_eq!(Some(Duration::MAX), exp.next()); assert_eq!(Some(Duration::MAX), exp.next()); } ``` -------------------------------- ### ExponentialBuilder Source: https://docs.rs/backon/1.6.0/src/backon/backoff/exponential.rs.html?search= A builder struct for configuring exponential backoff behavior. ```APIDOC ## ExponentialBuilder ### Description ExponentialBuilder is used to construct an `ExponentialBackoff` that offers delays with exponential retries. It provides methods to customize the retry strategy. ### Methods - `new()`: Creates a new `ExponentialBuilder` with default values (jitter: false, factor: 2, min_delay: 1s, max_delay: 60s, max_times: 3). - `with_jitter()`: Enables random jitter for the backoff. - `with_jitter_seed(seed: u64)`: Sets the seed value for the jitter random number generator. - `with_factor(factor: f32)`: Sets the multiplier factor for the backoff. - `with_min_delay(min_delay: Duration)`: Sets the minimum delay for the backoff. - `with_max_delay(max_delay: Duration)`: Sets the maximum delay for the backoff. - `without_max_delay()`: Removes the maximum delay constraint. - `with_max_times(max_times: usize)`: Sets the maximum number of retry attempts. - `without_max_times()`: Removes the maximum number of attempts constraint. - `with_total_delay(total_delay: Option)`: Sets the total cumulative delay limit for the backoff. ``` -------------------------------- ### PleaseEnableAFeatureOrProvideACustomSleeper Implementation Source: https://docs.rs/backon/1.6.0/src/backon/sleep.rs.html?search= A placeholder type that fails to compile if used as a Sleeper without configuration. ```rust /// A placeholder type that does not implement [`Sleeper`] and will therefore fail to compile if used as one. /// /// Users should enable a feature of this crate that provides a valid [`Sleeper`] implementation when this type appears in compilation errors. Alternatively, a custom [`Sleeper`] implementation should be provided where necessary, such as in [`crate::Retry::sleeper`]. #[doc(hidden)] #[allow(dead_code)] #[derive(Clone, Copy, Debug, Default)] pub struct PleaseEnableAFeatureOrProvideACustomSleeper; /// Implement `MaybeSleeper` but not `Sleeper`. impl MaybeSleeper for PleaseEnableAFeatureOrProvideACustomSleeper { type Sleep = Ready<()>; } ``` -------------------------------- ### ExponentialBuilder Methods Source: https://docs.rs/backon/1.6.0/backon/struct.ExponentialBuilder.html?search=u32+-%3E+bool Methods available on the ExponentialBuilder struct for configuring backoff behavior. ```APIDOC ## ExponentialBuilder ### Description Builder for configuring exponential backoff parameters. ### Methods - **new() -> Self**: Create a new ExponentialBuilder with default values. - **with_jitter(self) -> Self**: Enable jitter for the backoff. - **with_jitter_seed(self, seed: u64) -> Self**: Set the seed value for the jitter random number generator. - **with_factor(self, factor: f32) -> Self**: Set the factor for the backoff. - **with_min_delay(self, min_delay: Duration) -> Self**: Set the minimum delay for the backoff. - **with_max_delay(self, max_delay: Duration) -> Self**: Set the maximum delay for the backoff. - **without_max_delay(self) -> Self**: Set no maximum delay for the backoff. - **with_max_times(self, max_times: usize) -> Self**: Set the maximum number of attempts for the current backoff. - **without_max_times(self) -> Self**: Set no maximum number of attempts for the current backoff. - **with_total_delay(self, total_delay: Option) -> Self**: Set the total delay for the backoff. ``` -------------------------------- ### FibonacciBuilder::build Source: https://docs.rs/backon/1.6.0/backon/struct.FibonacciBuilder.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Constructs a new FibonacciBackoff instance using the builder. ```APIDOC ## fn build(self) -> Self::Backoff ### Description Constructs a new backoff using the builder. ### Returns - **Backoff** (FibonacciBackoff) - The constructed backoff instance. ``` -------------------------------- ### RetryWithContext::new Source: https://docs.rs/backon/1.6.0/src/backon/retry_with_context.rs.html?search=std%3A%3Avec Constructs a new RetryWithContext instance. ```APIDOC ## fn new(future_fn: FutureFn, backoff: B) -> Self ### Description Internal constructor for creating a new retry context manager. ### Parameters - **future_fn** (FutureFn) - Required - The function that produces the future to be retried. - **backoff** (B) - Required - The backoff implementation. ``` -------------------------------- ### FibonacciBuilder Source: https://docs.rs/backon/1.6.0/src/backon/backoff/fibonacci.rs.html?search= A builder struct for configuring Fibonacci-based backoff strategies. It allows customization of jitter, delay bounds, and retry limits. ```APIDOC ## FibonacciBuilder ### Description FibonacciBuilder is used to construct a FibonacciBackoff strategy. It provides methods to configure the retry behavior. ### Methods - **new()** - Creates a new `FibonacciBuilder` with default values (jitter: false, min_delay: 1s, max_delay: 60s, max_times: 3). - **with_jitter()** - Enables random jitter between (0, current_delay). - **with_jitter_seed(seed: u64)** - Sets a specific seed for the jitter random number generator. - **with_min_delay(min_delay: Duration)** - Sets the minimum delay for the backoff. - **with_max_delay(max_delay: Duration)** - Sets the maximum delay for the backoff. - **without_max_delay()** - Removes the maximum delay constraint. - **with_max_times(max_times: usize)** - Sets the maximum number of retry attempts. - **without_max_times()** - Removes the maximum retry attempts constraint. ``` -------------------------------- ### Fibonacci Backoff Unit Tests Source: https://docs.rs/backon/1.6.0/src/backon/backoff/fibonacci.rs.html?search=u32+-%3E+bool A collection of tests verifying default behavior, jitter, min/max delay constraints, and edge cases. ```rust #[test] fn test_fibonacci_default() { let mut fib = FibonacciBuilder::default().build(); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(None, fib.next()); } ``` ```rust #[test] fn test_fibonacci_jitter() { let mut fib = FibonacciBuilder::default().with_jitter().build(); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(1), "current: {v:?}"); assert!(v < Duration::from_secs(2), "current: {v:?}"); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(1), "current: {v:?}"); assert!(v < Duration::from_secs(2), "current: {v:?}"); let v = fib.next().expect("value must valid"); assert!(v >= Duration::from_secs(2), "current: {v:?}"); assert!(v < Duration::from_secs(3), "current: {v:?}"); assert_eq!(None, fib.next()); } ``` ```rust #[test] fn test_fibonacci_min_delay() { let mut fib = FibonacciBuilder::default() .with_min_delay(Duration::from_millis(500)) .build(); assert_eq!(Some(Duration::from_millis(500)), fib.next()); assert_eq!(Some(Duration::from_millis(500)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(None, fib.next()); } ``` ```rust #[test] fn test_fibonacci_max_delay() { let mut fib = FibonacciBuilder::default() .with_max_times(4) .with_max_delay(Duration::from_secs(2)) .build(); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(1)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(Some(Duration::from_secs(2)), fib.next()); assert_eq!(None, fib.next()); } ``` ```rust #[test] fn test_fibonacci_no_max_delay() { let mut fib = FibonacciBuilder::default() .with_max_times(4) .with_min_delay(Duration::from_secs(10_000_000_000_000_000_000)) .without_max_delay() .build(); assert_eq!( Some(Duration::from_secs(10_000_000_000_000_000_000)), fib.next() ); assert_eq!( Some(Duration::from_secs(10_000_000_000_000_000_000)), fib.next() ); assert_eq!(Some(Duration::MAX), fib.next()); ```