Skip to content

Commit 6c6da5d

Browse files
authored
Merge pull request #30 from InstaffoGmbH/add_first_in_millis_to_exponential
Add a configurable multiplication factor in `Exponential` delay
2 parents 2cbfe10 + 2c156fd commit 6c6da5d

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

src/delay.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,24 @@ use rand::{
1414
/// Each retry increases the delay since the last exponentially.
1515
#[derive(Debug)]
1616
pub struct Exponential {
17-
base: u64,
1817
current: u64,
18+
factor: f64,
1919
}
2020

2121
impl Exponential {
2222
/// Create a new `Exponential` using the given millisecond duration as the initial delay.
2323
pub fn from_millis(base: u64) -> Self {
2424
Exponential {
25-
base,
2625
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,
2735
}
2836
}
2937
}
@@ -34,11 +42,12 @@ impl Iterator for Exponential {
3442
fn next(&mut self) -> Option<Duration> {
3543
let duration = Duration::from_millis(self.current);
3644

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
3948
} else {
40-
self.current = U64_MAX;
41-
}
49+
next as u64
50+
};
4251

4352
Some(duration)
4453
}
@@ -50,6 +59,24 @@ impl From<Duration> for Exponential {
5059
}
5160
}
5261

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+
5380
/// Each retry uses a delay which is the sum of the two previous delays.
5481
///
5582
/// Depending on the problem at hand, a fibonacci delay strategy might

src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ impl<E> Display for Error<E>
203203
where
204204
E: StdError,
205205
{
206+
#[allow(deprecated)]
206207
fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
207208
write!(formatter, "{}", self.description())
208209
}
@@ -212,6 +213,7 @@ impl<E> StdError for Error<E>
212213
where
213214
E: StdError,
214215
{
216+
#[allow(deprecated)]
215217
fn description(&self) -> &str {
216218
match *self {
217219
Error::Operation { ref error, .. } => error.description(),
@@ -339,6 +341,23 @@ mod tests {
339341
assert_eq!(value, 2);
340342
}
341343

344+
#[test]
345+
fn succeeds_with_exponential_delay_with_factor() {
346+
let mut collection = vec![1, 2].into_iter();
347+
348+
let value = retry(
349+
Exponential::from_millis_with_factor(1000, 2.0),
350+
|| match collection.next() {
351+
Some(n) if n == 2 => Ok(n),
352+
Some(_) => Err("not 2"),
353+
None => Err("not 2"),
354+
},
355+
)
356+
.unwrap();
357+
358+
assert_eq!(value, 2);
359+
}
360+
342361
#[test]
343362
fn succeeds_with_ranged_delay() {
344363
let mut collection = vec![1, 2].into_iter();

0 commit comments

Comments
 (0)