fedimint_core/util/backoff_util.rs
1use std::time::Duration;
2
3pub use backon::{Backoff, FibonacciBackoff};
4use backon::{BackoffBuilder, FibonacciBuilder};
5
6/// Backoff strategy for background tasks.
7///
8/// Starts at 1s and increases to 60s, never giving up.
9pub fn background_backoff() -> FibonacciBackoff {
10 custom_backoff(Duration::from_secs(1), Duration::from_secs(60), None)
11}
12
13/// A backoff strategy for relatively quick foreground operations.
14///
15/// Starts at 200ms and increases to 5s. Will retry 10 times before giving up,
16/// with a maximum total delay between 20.8s and 22.8s depending on jitter.
17pub fn aggressive_backoff() -> FibonacciBackoff {
18 // Not accounting for jitter, the delays are:
19 // 0.2, 0.2, 0.4, 0.6, 1.0, 1.6, 2.6, 4.2, 5.0, 5.0.
20 //
21 // Jitter adds a random value between 0 and `min_delay` to each delay.
22 // Total jitter is between 0 and (10 * 0.2) = 2.0.
23 //
24 // Maximum possible delay including jitter is 22.8 seconds.
25 custom_backoff(Duration::from_millis(200), Duration::from_secs(5), Some(10))
26}
27
28#[cfg(test)]
29pub fn immediate_backoff(max_retries_or: Option<usize>) -> FibonacciBackoff {
30 custom_backoff(Duration::ZERO, Duration::ZERO, max_retries_or)
31}
32
33pub fn custom_backoff(
34 min_delay: Duration,
35 max_delay: Duration,
36 max_retries_or: Option<usize>,
37) -> FibonacciBackoff {
38 FibonacciBuilder::default()
39 .with_jitter()
40 .with_min_delay(min_delay)
41 .with_max_delay(max_delay)
42 .with_max_times(max_retries_or.unwrap_or(usize::MAX))
43 .build()
44}
45
46/// Retry every max 10s for up to one hour, with a more aggressive fibonacci
47/// backoff in the beginning to reduce expected latency.
48///
49/// Starts at 200ms increasing to 10s. Retries 360 times before giving up, with
50/// a maximum total delay between 3527.6s (58m 47.6s) and 3599.6s (59m 59.6s)
51/// depending on jitter.
52pub fn fibonacci_max_one_hour() -> FibonacciBackoff {
53 // Not accounting for jitter, the delays are:
54 // 0.2, 0.2, 0.4, 0.6, 1.0, 1.6, 2.6, 4.2, 6.8, 10.0...
55 //
56 // Jitter adds a random value between 0 and `min_delay` to each delay.
57 // Total jitter is between 0 and (360 * 0.2) = 72.0.
58 //
59 // Maximum possible delay including jitter is 3599.6s seconds.
60 custom_backoff(
61 Duration::from_millis(200),
62 Duration::from_secs(10),
63 Some(360),
64 )
65}