1use governor::{Quota, RateLimiter};
4use std::num::NonZeroU32;
5use std::sync::Arc;
6use tracing::debug;
7
8pub type CgRateLimiter = RateLimiter<
10 governor::state::NotKeyed,
11 governor::state::InMemoryState,
12 governor::clock::DefaultClock,
13>;
14
15pub const DEFAULT_REQUESTS_PER_MINUTE: u32 = 10;
19
20#[derive(Debug, Clone)]
22pub struct RateLimitConfig {
23 pub requests_per_minute: u32,
25}
26
27impl Default for RateLimitConfig {
28 fn default() -> Self {
29 Self {
30 requests_per_minute: DEFAULT_REQUESTS_PER_MINUTE,
31 }
32 }
33}
34
35impl RateLimitConfig {
36 pub fn new(requests_per_minute: u32) -> Self {
38 Self {
39 requests_per_minute,
40 }
41 }
42
43 pub fn build_limiter(&self) -> Arc<CgRateLimiter> {
45 let quota = Quota::per_minute(
46 NonZeroU32::new(self.requests_per_minute).unwrap_or(NonZeroU32::new(1).unwrap()),
47 );
48 Arc::new(RateLimiter::direct(quota))
49 }
50}
51
52pub async fn wait_for_permit(limiter: &CgRateLimiter) {
54 limiter.until_ready().await;
55 debug!("Rate limit permit acquired");
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_default_config() {
64 let config = RateLimitConfig::default();
65 assert_eq!(config.requests_per_minute, DEFAULT_REQUESTS_PER_MINUTE);
66 }
67
68 #[test]
69 fn test_custom_config() {
70 let config = RateLimitConfig::new(10);
71 assert_eq!(config.requests_per_minute, 10);
72 }
73
74 #[test]
75 fn test_build_limiter() {
76 let config = RateLimitConfig::new(5);
77 let limiter = config.build_limiter();
78 assert!(limiter.check().is_ok());
79 }
80}