From 83cadc0bf348aeaebc06322af8b7a092c4984826 Mon Sep 17 00:00:00 2001 From: Alexey <247128645+axkurcom@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:52:27 +0300 Subject: [PATCH] No lock-contention in ip-tracker --- src/ip_tracker.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ip_tracker.rs b/src/ip_tracker.rs index 492d642..5da8222 100644 --- a/src/ip_tracker.rs +++ b/src/ip_tracker.rs @@ -134,20 +134,20 @@ impl UserIpTracker { pub async fn get_recent_counts_for_users(&self, users: &[String]) -> HashMap { let window = *self.limit_window.read().await; let now = Instant::now(); - let mut recent_ips = self.recent_ips.write().await; + let recent_ips = self.recent_ips.read().await; let mut counts = HashMap::with_capacity(users.len()); for user in users { - let count = if let Some(user_recent) = recent_ips.get_mut(user) { - Self::prune_recent(user_recent, now, window); - user_recent.len() + let count = if let Some(user_recent) = recent_ips.get(user) { + user_recent + .values() + .filter(|seen_at| now.duration_since(**seen_at) <= window) + .count() } else { 0 }; counts.insert(user.clone(), count); } - - recent_ips.retain(|_, user_recent| !user_recent.is_empty()); counts } @@ -168,21 +168,22 @@ impl UserIpTracker { pub async fn get_recent_ips_for_users(&self, users: &[String]) -> HashMap> { let window = *self.limit_window.read().await; let now = Instant::now(); - let mut recent_ips = self.recent_ips.write().await; + let recent_ips = self.recent_ips.read().await; let mut out = HashMap::with_capacity(users.len()); for user in users { - let mut ips = if let Some(user_recent) = recent_ips.get_mut(user) { - Self::prune_recent(user_recent, now, window); - user_recent.keys().copied().collect::>() + let mut ips = if let Some(user_recent) = recent_ips.get(user) { + user_recent + .iter() + .filter(|(_, seen_at)| now.duration_since(**seen_at) <= window) + .map(|(ip, _)| *ip) + .collect::>() } else { Vec::new() }; ips.sort(); out.insert(user.clone(), ips); } - - recent_ips.retain(|_, user_recent| !user_recent.is_empty()); out }