Skip to content

Commit

Permalink
graph: fix backoff overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
YaroShkvorets authored and lutter committed Mar 6, 2023
1 parent e1f04cf commit f8d0143
Showing 1 changed file with 69 additions and 1 deletion.
70 changes: 69 additions & 1 deletion graph/src/util/backoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl ExponentialBackoff {
}

pub fn delay(&self) -> Duration {
let mut delay = self.base.saturating_mul(1 << self.attempt);
let mut delay = self.base.saturating_mul(1u32 << self.attempt.min(31));
if delay > self.ceiling {
delay = self.ceiling;
}
Expand All @@ -50,3 +50,71 @@ impl ExponentialBackoff {
self.attempt = 0;
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::time::Instant;

#[test]
fn test_delay() {
let mut backoff =
ExponentialBackoff::new(Duration::from_millis(500), Duration::from_secs(5));

// First delay should be base (0.5s)
assert_eq!(backoff.next_attempt(), Duration::from_millis(500));

// Second delay should be 1s (base * 2^1)
assert_eq!(backoff.next_attempt(), Duration::from_secs(1));

// Third delay should be 2s (base * 2^2)
assert_eq!(backoff.next_attempt(), Duration::from_secs(2));

// Fourth delay should be 4s (base * 2^3)
assert_eq!(backoff.next_attempt(), Duration::from_secs(4));

// Seventh delay should be ceiling (5s)
assert_eq!(backoff.next_attempt(), Duration::from_secs(5));

// Eighth delay should also be ceiling (5s)
assert_eq!(backoff.next_attempt(), Duration::from_secs(5));
}

#[test]
fn test_overflow_delay() {
let mut backoff =
ExponentialBackoff::new(Duration::from_millis(500), Duration::from_secs(45));

// 31st should be ceiling (45s) without overflowing
backoff.attempt = 31;
assert_eq!(backoff.next_attempt(), Duration::from_secs(45));
assert_eq!(backoff.next_attempt(), Duration::from_secs(45));

backoff.attempt = 123456;
assert_eq!(backoff.next_attempt(), Duration::from_secs(45));
}

#[tokio::test]
async fn test_sleep_async() {
let mut backoff =
ExponentialBackoff::new(Duration::from_secs_f32(0.1), Duration::from_secs_f32(0.2));

let start = Instant::now();
backoff.sleep_async().await;
let elapsed = start.elapsed();

assert!(elapsed >= Duration::from_secs_f32(0.1) && elapsed < Duration::from_secs_f32(0.15));

let start = Instant::now();
backoff.sleep_async().await;
let elapsed = start.elapsed();

assert!(elapsed >= Duration::from_secs_f32(0.2) && elapsed < Duration::from_secs_f32(0.25));

let start = Instant::now();
backoff.sleep_async().await;
let elapsed = start.elapsed();

assert!(elapsed >= Duration::from_secs_f32(0.2) && elapsed < Duration::from_secs_f32(0.25));
}
}

0 comments on commit f8d0143

Please sign in to comment.