retry_block/delay/
random.rs1use std::{
2 ops::{Range as StdRange, RangeInclusive},
3 time::Duration,
4};
5
6use rand::{
7 distributions::{Distribution, Uniform},
8 thread_rng,
9};
10
11#[derive(Debug, Clone)]
13pub struct Range {
14 distribution: Uniform<u64>,
15}
16
17impl Range {
18 pub fn from_millis_exclusive(minimum: u64, maximum: u64) -> Self {
24 Range {
25 distribution: Uniform::new(minimum, maximum),
26 }
27 }
28
29 pub fn from_millis_inclusive(minimum: u64, maximum: u64) -> Self {
35 Range {
36 distribution: Uniform::new_inclusive(minimum, maximum),
37 }
38 }
39}
40
41impl Iterator for Range {
42 type Item = Duration;
43
44 fn next(&mut self) -> Option<Duration> {
45 Some(Duration::from_millis(
46 self.distribution.sample(&mut thread_rng()),
47 ))
48 }
49}
50
51impl From<StdRange<Duration>> for Range {
52 fn from(range: StdRange<Duration>) -> Self {
53 Self::from_millis_exclusive(range.start.as_millis() as u64, range.end.as_millis() as u64)
54 }
55}
56
57impl From<RangeInclusive<Duration>> for Range {
58 fn from(range: RangeInclusive<Duration>) -> Self {
59 Self::from_millis_inclusive(
60 range.start().as_millis() as u64,
61 range.end().as_millis() as u64,
62 )
63 }
64}
65
66pub fn jitter(duration: Duration) -> Duration {
68 jitter_rng(duration, &mut thread_rng())
69}
70
71pub fn jitter_rng(duration: Duration, rng: &mut impl rand::Rng) -> Duration {
72 duration.mul_f64(rng.gen())
73}
74
75#[cfg(test)]
76mod test {
77 use crate::delay::jitter_rng;
78 use rand::SeedableRng;
79 use rand_xorshift::XorShiftRng;
80 use std::time::Duration;
81 #[test]
82 fn test_jitter_1_sec() {
83 let mut rng = XorShiftRng::seed_from_u64(0);
84
85 let duration = Duration::from_millis(1000);
86 assert_ne!(
87 jitter_rng(duration, &mut rng),
88 jitter_rng(duration, &mut rng)
89 )
90 }
91}