feat(supervisor): exponential backoff calculator
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Backoff {
|
||||||
|
initial: Duration,
|
||||||
|
max: Duration,
|
||||||
|
current: Option<Duration>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backoff {
|
||||||
|
pub fn new(initial: Duration, max: Duration) -> Self {
|
||||||
|
Self {
|
||||||
|
initial,
|
||||||
|
max,
|
||||||
|
current: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self) -> Duration {
|
||||||
|
let next = match self.current {
|
||||||
|
None => self.initial,
|
||||||
|
Some(d) => (d * 2).min(self.max),
|
||||||
|
};
|
||||||
|
self.current = Some(next);
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.current = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn starts_at_initial() {
|
||||||
|
let mut b = Backoff::new(Duration::from_secs(1), Duration::from_secs(30));
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn doubles_each_call() {
|
||||||
|
let mut b = Backoff::new(Duration::from_secs(1), Duration::from_secs(30));
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(1));
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(2));
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(4));
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn caps_at_max() {
|
||||||
|
let mut b = Backoff::new(Duration::from_secs(1), Duration::from_secs(5));
|
||||||
|
for _ in 0..10 {
|
||||||
|
b.next();
|
||||||
|
}
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reset_starts_over() {
|
||||||
|
let mut b = Backoff::new(Duration::from_secs(1), Duration::from_secs(30));
|
||||||
|
b.next();
|
||||||
|
b.next();
|
||||||
|
b.next();
|
||||||
|
b.reset();
|
||||||
|
assert_eq!(b.next(), Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user