pub trait RetryableWithContext<B: BackoffBuilder, T, E, Ctx, Fut: Future<Output = (Ctx, Result<T, E>)>, FutureFn: FnMut(Ctx) -> Fut> {
    // Required method
    fn retry(self, builder: &B) -> Retry<B::Backoff, T, E, Ctx, Fut, FutureFn>;
}
Expand description

RetryableWithContext will add retry support for functions that produces a futures with results and context.

That means all types that implement FnMut(Ctx) -> impl Future<Output = (Ctx, Result<T, E>)> will be able to use retry.

This will allow users to pass a context to the function and return it back while retry finish.

§Example

Without context, we could meet errors like the following:

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

But with context support, we can implement in this way:

use anyhow::anyhow;
use anyhow::Result;
use backon::ExponentialBuilder;
use backon::RetryableWithContext;

struct Test;

impl Test {
    async fn hello(&mut self) -> Result<usize> {
        Err(anyhow!("not retryable"))
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
    let mut test = Test;

    // (Test, Result<usize>)
    let (_, result) = {
        |mut v: Test| async {
            let res = v.hello().await;
            (v, res)
        }
    }
    .retry(&ExponentialBuilder::default())
    .context(test)
    .await;

    Ok(())
}

Required Methods§

source

fn retry(self, builder: &B) -> Retry<B::Backoff, T, E, Ctx, Fut, FutureFn>

Generate a new retry

Implementors§

source§

impl<B, T, E, Ctx, Fut, FutureFn> RetryableWithContext<B, T, E, Ctx, Fut, FutureFn> for FutureFn
where B: BackoffBuilder, Fut: Future<Output = (Ctx, Result<T, E>)>, FutureFn: FnMut(Ctx) -> Fut,