use std::sync::Arc;
use std::time::Duration;
use tower_governor::governor::{GovernorConfig, GovernorConfigBuilder};
use tower_governor::key_extractor::SmartIpKeyExtractor;
pub use tower_governor::GovernorLayer;
type HeaderMiddleware = ::governor::middleware::StateInformationMiddleware;
pub type RateLimitConfig = GovernorConfig<SmartIpKeyExtractor, HeaderMiddleware>;
pub fn build_rate_limit_config(burst: u32) -> anyhow::Result<Arc<RateLimitConfig>> {
let mut builder = GovernorConfigBuilder::default();
builder.per_second(u64::from(burst));
builder.burst_size(burst);
let mut builder = builder.key_extractor(SmartIpKeyExtractor);
let mut builder = builder.use_headers();
let config = Arc::new(
builder
.finish()
.ok_or_else(|| anyhow::anyhow!("failed to build rate limiter configuration"))?,
);
spawn_limiter_cleanup(&config);
Ok(config)
}
fn spawn_limiter_cleanup(config: &Arc<RateLimitConfig>) {
let limiter = config.limiter().clone();
let interval = Duration::from_secs(60);
std::thread::spawn(move || loop {
std::thread::sleep(interval);
tracing::debug!("rate limiter cleanup: {} tracked IPs", limiter.len());
limiter.retain_recent();
});
}
#[cfg(test)]
#[path = "rate_limit_tests.rs"]
mod tests;