From 979e1c7411adbef87ab42e7dca9770fa935493e9 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sun, 15 Mar 2026 04:36:23 +0000 Subject: [PATCH] fix: restore Instant for rate limiters, keep SystemTime for sessions Rate limiters correctly use monotonic Instant. Session TTL uses SystemTime for wall-clock accuracy across sleep/hibernate. Co-Authored-By: Claude Opus 4.6 (1M context) --- core/archipelago/src/session.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/archipelago/src/session.rs b/core/archipelago/src/session.rs index 795f6ae2..8fa438d4 100644 --- a/core/archipelago/src/session.rs +++ b/core/archipelago/src/session.rs @@ -2,7 +2,7 @@ use sha2::{Digest, Sha256}; use std::collections::HashMap; use std::net::IpAddr; use std::sync::Arc; -use std::time::SystemTime; +use std::time::{Instant, SystemTime}; use tokio::sync::RwLock; use zeroize::Zeroize; @@ -262,7 +262,7 @@ impl LoginRateLimiter { pub async fn check(&self, ip: IpAddr) -> bool { let mut attempts = self.attempts.write().await; - let now = SystemTime::now(); + let now = Instant::now(); let entry = attempts.entry(ip).or_default(); entry.retain(|t| now.duration_since(*t).as_secs() < WINDOW_SECS); entry.len() < MAX_ATTEMPTS @@ -271,7 +271,7 @@ impl LoginRateLimiter { pub async fn record_failure(&self, ip: IpAddr) { let mut attempts = self.attempts.write().await; let entry = attempts.entry(ip).or_default(); - entry.push(SystemTime::now()); + entry.push(Instant::now()); } } @@ -280,7 +280,7 @@ impl LoginRateLimiter { #[derive(Clone)] pub struct EndpointRateLimiter { /// Map of (method, ip) -> list of request timestamps - requests: Arc>>>, + requests: Arc>>>, // Instant for monotonic rate limiting /// Per-method configuration: (max_requests, window_secs) limits: Arc>, } @@ -338,7 +338,7 @@ impl EndpointRateLimiter { let key = (method.to_string(), ip); let mut requests = self.requests.write().await; - let now = SystemTime::now(); + let now = Instant::now(); let entry = requests.entry(key).or_default(); entry.retain(|t| now.duration_since(*t).as_secs() < window); entry.len() < max_req @@ -352,13 +352,13 @@ impl EndpointRateLimiter { let key = (method.to_string(), ip); let mut requests = self.requests.write().await; let entry = requests.entry(key).or_default(); - entry.push(SystemTime::now()); + entry.push(Instant::now()); } /// Periodic cleanup of expired entries. pub async fn cleanup(&self) { let mut requests = self.requests.write().await; - let now = SystemTime::now(); + let now = Instant::now(); requests.retain(|(method, _), timestamps| { let window = self .limits