From 5a7762ac1328df5e9e4da0bdbdcf34808966054b Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sat, 21 Feb 2026 19:50:55 +0300 Subject: [PATCH] rate-limiter: re-validate burst window in loop after sleep Signed-off-by: NotAShelf Change-Id: Iaa63eef1f055b9a98c90739025bd3ff36a6a6964 --- src/rate_limiter.rs | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/rate_limiter.rs b/src/rate_limiter.rs index 871c666..f5832f8 100644 --- a/src/rate_limiter.rs +++ b/src/rate_limiter.rs @@ -72,32 +72,29 @@ impl RateLimiter { let interval = Duration::from_secs(60) / rate.max(1); - let mut inner = self.inner.lock().await; - let now = Instant::now(); - let platform_requests = - inner.requests.entry(platform.to_string()).or_default(); + loop { + let mut inner = self.inner.lock().await; + let now = Instant::now(); + let platform_requests = + inner.requests.entry(platform.to_string()).or_default(); - platform_requests - .retain(|t| now.duration_since(*t) < Duration::from_secs(60)); + platform_requests + .retain(|t| now.duration_since(*t) < Duration::from_secs(60)); - if platform_requests.len() >= burst as usize - && let Some(oldest) = platform_requests.first() - { - let wait_time = interval.saturating_sub(now.duration_since(*oldest)); - if wait_time > Duration::ZERO { - drop(inner); - tokio::time::sleep(wait_time).await; - let mut inner = self.inner.lock().await; - let platform_requests = - inner.requests.entry(platform.to_string()).or_default(); - platform_requests.push(Instant::now()); - return Ok(()); + if platform_requests.len() >= burst as usize + && let Some(oldest) = platform_requests.first() + { + let wait_time = interval.saturating_sub(now.duration_since(*oldest)); + if wait_time > Duration::ZERO { + drop(inner); + tokio::time::sleep(wait_time).await; + continue; + } } + + platform_requests.push(Instant::now()); + return Ok(()); } - - platform_requests.push(Instant::now()); - - Ok(()) } pub async fn wait_for(&self, platform: &str) {