use crate::config::RateConfig;
use governor::{DefaultDirectRateLimiter, Quota, RateLimiter};
use std::sync::Arc;
use tokio::sync::{OwnedSemaphorePermit, Semaphore};
#[derive(Clone)]
pub struct RateGate {
limiter: Arc<DefaultDirectRateLimiter>,
inflight: Arc<Semaphore>,
}
impl RateGate {
pub fn new(cfg: RateConfig) -> Self {
let quota = Quota::per_second(cfg.rps).allow_burst(cfg.burst);
let limiter = Arc::new(RateLimiter::direct(quota));
let inflight = Arc::new(Semaphore::new(cfg.max_inflight.get() as usize));
Self { limiter, inflight }
}
pub async fn wait_turn(&self) {
self.limiter.until_ready().await;
}
pub async fn acquire_inflight(&self) -> OwnedSemaphorePermit {
self.inflight
.clone()
.acquire_owned()
.await
.expect("semaphore closed")
}
}