Adaptive backoff provides a mechanism to intelligently back off use of rate
limited or failure operations through sources simples structs, Backoffs
. Backoffs
take input on success and failure, then return a duration to wait.
For an adaptive backoff, as the failure and success calls increase the returned duration eventually converges on a value to avoid rate limiting of requests.
Include within your Cargo.toml
:
adaptive_backoff = "0.2"
And follow an example below:
Below is an example of an adapative ExponentialBackoff
which works from a queue
and converges on a minimal delay duration between calls. It grows by a factor of
2.0
to a maximum of 300
seconds.
```rust use std::time::Duration; use adaptive_backoff::prelude::*;
let mut backoff = ExponentialBackoffBuilder::default() .factor(2.0) .max(Duration::from_secs(300)) .adaptive() .build() .unwrap();
while let Some(item) = queue.pop() { loop { match workeriter(&conn, &item).await { Ok() => { delayfor(backoff.success()).await; break; } Err() => delay_for(backoff.fail()).await, } } } ```
If adaptive is omitted from the example above, a simple backoff is returned.
Its API lacks success()
and fail()
, instead it can only return increasing
delays with wait()
until reset()
is called to return it.
```rust use std::time::Duration; use adaptive_backoff::prelude::*;
let mut backoff = ExponentialBackoffBuilder::default() .factor(2.0) .max(Duration::from_secs(30)) .build() .unwrap();
while let Some(item) = queue.pop() { loop { match workeriter(&conn, &item).await { Ok() => { delayfor(backoff.wait()).await; break; } Err() => delay_for(backoff.wait()).await, } }
backoff.reset();
} ```
There are tests for backoff implementations which contain example use of the external API with expected output. See both the simple exponential example and the adaptive exponential backoff example.