use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Mutex;
use tokio::time::Instant;
#[derive(Debug, Clone)]
pub struct RateLimiter {
blocked_until: Arc<Mutex<Option<Instant>>>,
enabled: bool,
}
impl RateLimiter {
pub fn new() -> Self {
Self {
blocked_until: Arc::new(Mutex::new(None)),
enabled: true,
}
}
pub fn disabled() -> Self {
Self {
blocked_until: Arc::new(Mutex::new(None)),
enabled: false,
}
}
pub fn is_disabled(&self) -> bool {
!self.enabled
}
pub async fn record(&self, retry_after: Duration) {
if !self.enabled {
return;
}
let until = Instant::now() + retry_after;
let mut guard = self.blocked_until.lock().await;
*guard = Some(until);
}
pub(crate) async fn wait(&self) {
if !self.enabled {
return;
}
let deadline = {
let guard = self.blocked_until.lock().await;
*guard
};
if let Some(until) = deadline.filter(|&t| t > Instant::now()) {
tokio::time::sleep_until(until).await;
}
}
}
impl Default for RateLimiter {
fn default() -> Self {
Self::new()
}
}