use std::sync::Arc;
use tokio::sync::Semaphore;
#[derive(Debug, Clone)]
pub struct RateLimiter {
semaphore: Arc<Semaphore>,
}
impl RateLimiter {
pub fn new(max_permits: usize) -> Self {
Self {
semaphore: Arc::new(Semaphore::new(max_permits)),
}
}
#[allow(clippy::significant_drop_tightening)] pub async fn acquire(&self, cost: u32) -> crate::error::Result<()> {
let permit =
self.semaphore.acquire_many(cost).await.map_err(|e| {
crate::error::MktError::ConfigError(format!("Rate limiter error: {e}"))
})?;
permit.forget();
self.semaphore.add_permits(cost as usize);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn acquire_within_budget() {
let limiter = RateLimiter::new(100);
let result = limiter.acquire(1).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn acquire_multiple_permits() {
let limiter = RateLimiter::new(100);
let result = limiter.acquire(3).await;
assert!(result.is_ok());
}
}