use std::collections::VecDeque;
use std::sync::Mutex;
use std::time::{Duration, Instant};
pub(crate) struct WindowRateLimiter {
window: Duration,
max_requests: usize,
stamps: Mutex<VecDeque<Instant>>,
}
impl WindowRateLimiter {
pub fn companies_house_default() -> Self {
Self {
window: Duration::from_secs(5 * 60),
max_requests: 600,
stamps: Mutex::new(VecDeque::new()),
}
}
pub async fn acquire(&self) {
loop {
let wait = {
let mut stamps = self.stamps.lock().unwrap_or_else(|p| p.into_inner());
let now = Instant::now();
while stamps
.front()
.is_some_and(|t| now.duration_since(*t) > self.window)
{
stamps.pop_front();
}
if stamps.len() < self.max_requests {
stamps.push_back(now);
return;
}
let oldest = *stamps.front().expect("non-empty when at capacity");
self.window.saturating_sub(now.duration_since(oldest))
};
if wait.is_zero() {
tokio::time::sleep(Duration::from_millis(1)).await;
} else {
tokio::time::sleep(wait).await;
}
}
}
}