use std::collections::VecDeque;
use std::time::{Duration, Instant};
use parking_lot::Mutex;
pub(crate) struct SlidingWindow {
limit: u32,
window: Duration,
timestamps: Mutex<VecDeque<Instant>>,
}
impl SlidingWindow {
pub(crate) fn new(limit: u32, window: Duration) -> Self {
Self {
limit,
window,
timestamps: Mutex::new(VecDeque::with_capacity(limit as usize)),
}
}
pub(crate) fn try_acquire(&self) -> bool {
let now = Instant::now();
let cutoff = now - self.window;
let mut ts = self.timestamps.lock();
while ts.front().is_some_and(|t| *t < cutoff) {
ts.pop_front();
}
if ts.len() < self.limit as usize {
ts.push_back(now);
true
} else {
false
}
}
#[allow(dead_code)]
pub(crate) fn remaining(&self) -> u32 {
let now = Instant::now();
let cutoff = now - self.window;
let ts = self.timestamps.lock();
let active = ts.iter().filter(|t| **t >= cutoff).count();
self.limit.saturating_sub(active as u32)
}
}