Retry-If
A predicate-based retry decorator for retrying arbitrary functions using an exponential backoff strategy.
This library aims to make decorating your code with a retry strategy as easy as possible, all that's required is a defined retry strategy and a function that determines if the output of your code needs to be retried.
Example: Retrying a Result-producing Function on Err(...)
The below example sets up a basic retry configuration that will retry up to five times, waiting at first 1 second, then 2 seconds, 4 seconds, etc. There is no configured maximum time to retry across all attempts (t_wait_max), nor is there any maximum waiting time on each backoff (backoff_max).
use ;
use TryFromIntError;
use Duration;
use ;
const BACKOFF_CONFIG: ExponentialBackoffConfig = ExponentialBackoffConfig ;
// this takes an address of the same type as the output of the decorated function.
// It returns true if the function should be retried based on the result
async
async
Tracing
The crate exposes tracing as a feature to enable logging using the tokio tracing library's tracing::info! for
each of the retry attempts. These currently take the form of: Sleeping {Duration:?} on attempt {i32}. The output
traces will take on whatever instrumented scope is given to the parent function.
Limitations
#[retry(...)] can decorate almost all cases of async functions. This includes:
- free functions such as
async fn do_thing() -> i32 - methods in impl blocks such as
async fn do_thing(&mut self) -> bool - trait implementations in
impl <Trait> for <Struct> {}blocks, such asasync fn do_thing(&self) -> String
It cannot, however, decorate impl functions that consume themselves, since this requires the first call
consuming self.
A non-working example of this is shown below, where to_thing() consumes self, making a second call impossible.
Contributions
Please reach out if you encounter edge cases, have any suggestions for improving the API, or have any clarifications that can be made.