use std::time::{Duration, Instant};
use super::mechanism::ThrottleMechanism;
pub struct StupidThrottle {
time_between_requests: Duration,
last_request: Option<Instant>,
}
impl StupidThrottle {
pub fn new(requests_per_minute: f32) -> Self {
Self {
time_between_requests: Duration::from_secs(60).div_f32(requests_per_minute),
last_request: None,
}
}
}
impl ThrottleMechanism for StupidThrottle {
fn timeout_delay(&mut self, now: Instant) -> std::time::Duration {
if let Some(last) = self.last_request {
if now >= last {
let duration = now - last;
if duration >= self.time_between_requests {
self.last_request = Some(now);
Duration::ZERO
} else {
let difference = self.time_between_requests - duration;
self.last_request = Some(now + difference);
difference
}
} else {
let duration = last - now + self.time_between_requests;
self.last_request = Some(now + duration);
duration
}
} else {
self.last_request = Some(now);
Duration::ZERO
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn throttle_stupid_no_wait_needede() {
let mut stupid = StupidThrottle::new(6.0);
let now = Instant::now();
let after_11_seconds = now + Duration::from_secs(11);
assert_eq!(Duration::from_secs(0), stupid.timeout_delay(now));
assert_eq!(
Duration::from_secs(0),
stupid.timeout_delay(after_11_seconds)
);
}
#[test]
fn throttle_stupid_wait_needede() {
let mut stupid = StupidThrottle::new(6.0);
let now = Instant::now();
let after_5_seconds = now + Duration::from_secs(5);
assert_eq!(Duration::from_secs(0), stupid.timeout_delay(now));
assert_eq!(
Duration::from_secs(5),
stupid.timeout_delay(after_5_seconds)
);
}
#[test]
fn throttle_stupid_two_wait_needed() {
let mut stupid = StupidThrottle::new(6.0);
let now = Instant::now();
let after_5_seconds = now + Duration::from_secs(5);
let after_7_seconds = now + Duration::from_secs(7);
assert_eq!(Duration::from_secs(0), stupid.timeout_delay(now));
assert_eq!(
Duration::from_secs(5),
stupid.timeout_delay(after_5_seconds)
);
assert_eq!(
Duration::from_secs(13),
stupid.timeout_delay(after_7_seconds)
);
}
#[test]
fn throttle_stupid_multiple_wait_needed() {
let mut stupid = StupidThrottle::new(6.0);
let now = Instant::now();
let after_3_seconds = now + Duration::from_secs(3);
let after_5_seconds = now + Duration::from_secs(5);
let after_7_seconds = now + Duration::from_secs(7);
assert_eq!(Duration::from_secs(0), stupid.timeout_delay(now));
assert_eq!(
Duration::from_secs(7),
stupid.timeout_delay(after_3_seconds)
);
assert_eq!(
Duration::from_secs(15),
stupid.timeout_delay(after_5_seconds)
);
assert_eq!(
Duration::from_secs(23),
stupid.timeout_delay(after_7_seconds)
);
}
#[test]
fn throttle_stupid_mixed_wait_needed() {
let mut stupid = StupidThrottle::new(6.0);
let now = Instant::now();
let after_5_seconds = now + Duration::from_secs(5);
let after_7_seconds = now + Duration::from_secs(7);
let after_13_seconds = now + Duration::from_secs(13);
assert_eq!(Duration::from_secs(0), stupid.timeout_delay(now));
assert_eq!(
Duration::from_secs(5),
stupid.timeout_delay(after_5_seconds)
);
assert_eq!(
Duration::from_secs(13),
stupid.timeout_delay(after_7_seconds)
);
assert_eq!(
Duration::from_secs(17),
stupid.timeout_delay(after_13_seconds)
);
}
}