From fc8e0657a0db04b9d0a3c020fb3a854a781c9db4 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 4 Apr 2026 16:40:49 +0200 Subject: [PATCH] change that oldest_active_game_age_sec not gets inflated when redis already deleted it --- server/metrics/ServerMetricsCollector.py | 48 +++++++++++++++--------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/server/metrics/ServerMetricsCollector.py b/server/metrics/ServerMetricsCollector.py index 7037401..2c27c36 100644 --- a/server/metrics/ServerMetricsCollector.py +++ b/server/metrics/ServerMetricsCollector.py @@ -108,6 +108,36 @@ class ServerMetricsCollector: # ── snapshot builders ───────────────────────────────────────────────────── + def _calc_active_game_stats(self, game_last_seen_unix:dict) -> tuple[int, int, int]: + """Returns (report_active_games, report_stale_candidates, oldest_active_age_sec).""" + now = int(time.time()) + stale_candidates = sum( + 1 + for last_seen in game_last_seen_unix.values() + if now - last_seen >= self._stale_game_timeout_sec + ) + + if self._game_state_backend_is_redis: + # Redis auto-expires stale keys via TTL, so stale games are already gone from the + # server's perspective. We exclude them from all metrics so we only report games + # that are actually still alive in Redis. + report_active_games = len(game_last_seen_unix) - stale_candidates + report_stale_candidates = 0 + # Only include non-stale timestamps when calculating the oldest active game age, + # so a game that Redis already deleted doesn't inflate the age metric. + active_last_seen = [ + last_seen + for last_seen in game_last_seen_unix.values() + if now - last_seen < self._stale_game_timeout_sec + ] + else: + report_active_games = len(game_last_seen_unix) + report_stale_candidates = stale_candidates + active_last_seen = list(game_last_seen_unix.values()) + + oldest_active_age = max(0, now - min(active_last_seen)) if active_last_seen else 0 + return report_active_games, report_stale_candidates, oldest_active_age + def build_local_snapshot(self, game_last_seen_unix:dict, game_move_counts:dict) -> dict: games_ended = self._metrics['games_ended'] total_moves = self._metrics['total_moves'] @@ -117,23 +147,7 @@ class ServerMetricsCollector: self._metrics['move_response_time_ms_total'] / total_moves if total_moves else 0.0 ) - now = int(time.time()) - oldest_active_age = ( - max(0, now - min(game_last_seen_unix.values())) if game_last_seen_unix else 0 - ) - - stale_candidates = sum( - 1 - for last_seen in game_last_seen_unix.values() - if now - last_seen >= self._stale_game_timeout_sec - ) - - if self._game_state_backend_is_redis: - report_stale_candidates = 0 - report_active_games = len(game_last_seen_unix) - stale_candidates - else: - report_stale_candidates = stale_candidates - report_active_games = len(game_last_seen_unix) + report_active_games, report_stale_candidates, oldest_active_age = self._calc_active_game_stats(game_last_seen_unix) return { **self._metrics,