exponential_backoff/
into_iter.rs

1use super::Backoff;
2use fastrand::Rng;
3use std::{iter, time::Duration};
4
5/// An exponential backoff iterator.
6#[derive(Debug, Clone)]
7pub struct IntoIter {
8    inner: Backoff,
9    rng: Rng,
10    attempts: u32,
11}
12
13impl IntoIter {
14    pub(crate) fn new(inner: Backoff) -> Self {
15        Self {
16            attempts: 0,
17            rng: Rng::new(),
18            inner,
19        }
20    }
21}
22
23impl iter::Iterator for IntoIter {
24    type Item = Option<Duration>;
25
26    #[inline]
27    fn next(&mut self) -> Option<Self::Item> {
28        // Check whether we've exceeded the number of attempts,
29        // or whether we're on our last attempt. We don't want to sleep after
30        // the last attempt.
31        if self.attempts == self.inner.max_attempts {
32            return None;
33        } else if self.attempts == self.inner.max_attempts - 1 {
34            self.attempts = self.attempts.saturating_add(1);
35            return Some(None);
36        }
37
38        self.attempts = self.attempts.saturating_add(1);
39
40        // Create exponential duration.
41        let exponent = self.inner.factor.saturating_pow(self.attempts);
42        let duration = self.inner.min.saturating_mul(exponent);
43
44        // Apply jitter. Uses multiples of 100 to prevent relying on floats.
45        let jitter_factor = (self.inner.jitter * 100f32) as u32;
46        let random = self.rng.u32(0..jitter_factor * 2);
47        let mut duration = duration.saturating_mul(100);
48        if random < jitter_factor {
49            let jitter = duration.saturating_mul(random) / 100;
50            duration = duration.saturating_sub(jitter);
51        } else {
52            let jitter = duration.saturating_mul(random / 2) / 100;
53            duration = duration.saturating_add(jitter);
54        };
55        duration /= 100;
56
57        // Make sure it doesn't exceed upper / lower bounds.
58        duration = duration.clamp(self.inner.min, self.inner.max);
59
60        Some(Some(duration))
61    }
62}