@@ -14,16 +14,24 @@ use rand::{
14
14
/// Each retry increases the delay since the last exponentially.
15
15
#[ derive( Debug ) ]
16
16
pub struct Exponential {
17
- base : u64 ,
18
17
current : u64 ,
18
+ factor : f64 ,
19
19
}
20
20
21
21
impl Exponential {
22
22
/// Create a new `Exponential` using the given millisecond duration as the initial delay.
23
23
pub fn from_millis ( base : u64 ) -> Self {
24
24
Exponential {
25
- base,
26
25
current : base,
26
+ factor : base as f64 ,
27
+ }
28
+ }
29
+
30
+ /// Create a new `Exponential` using the given millisecond duration as the initial delay and a variable multiplication factor.
31
+ pub fn from_millis_with_factor ( base : u64 , factor : f64 ) -> Self {
32
+ Exponential {
33
+ current : base,
34
+ factor,
27
35
}
28
36
}
29
37
}
@@ -34,11 +42,12 @@ impl Iterator for Exponential {
34
42
fn next ( & mut self ) -> Option < Duration > {
35
43
let duration = Duration :: from_millis ( self . current ) ;
36
44
37
- if let Some ( next) = self . current . checked_mul ( self . base ) {
38
- self . current = next;
45
+ let next = ( self . current as f64 ) * self . factor ;
46
+ self . current = if next > ( U64_MAX as f64 ) {
47
+ U64_MAX
39
48
} else {
40
- self . current = U64_MAX ;
41
- }
49
+ next as u64
50
+ } ;
42
51
43
52
Some ( duration)
44
53
}
@@ -50,6 +59,24 @@ impl From<Duration> for Exponential {
50
59
}
51
60
}
52
61
62
+ #[ test]
63
+ fn exponential_with_factor ( ) {
64
+ let mut iter = Exponential :: from_millis_with_factor ( 1000 , 2.0 ) ;
65
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 1000 ) ) ) ;
66
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 2000 ) ) ) ;
67
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 4000 ) ) ) ;
68
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 8000 ) ) ) ;
69
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 16000 ) ) ) ;
70
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( 32000 ) ) ) ;
71
+ }
72
+
73
+ #[ test]
74
+ fn exponential_overflow ( ) {
75
+ let mut iter = Exponential :: from_millis ( U64_MAX ) ;
76
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( U64_MAX ) ) ) ;
77
+ assert_eq ! ( iter. next( ) , Some ( Duration :: from_millis( U64_MAX ) ) ) ;
78
+ }
79
+
53
80
/// Each retry uses a delay which is the sum of the two previous delays.
54
81
///
55
82
/// Depending on the problem at hand, a fibonacci delay strategy might
0 commit comments