Files
comunidadhll/ai/tasks/done/TASK-267-investigate-current-match-live-data-staleness-and-clean-copy.md

12 KiB

id, title, status, type, team, supporting_teams, roadmap_item, priority
id title status type team supporting_teams roadmap_item priority
TASK-267 Investigate current match live data staleness and clean copy in-progress investigation Backend Senior
Frontend Senior
current-match high

TASK-267 - Investigate current match live data staleness and clean copy

Goal

Determine whether the current match killfeed and live player statistics are stale in the API, stale in frontend rendering, or mismatched against CRCON/RCON live data. Apply only the requested visible copy cleanup unless the diagnosis proves a safe code fix is required.

Context

The current match page can show older live stats than CRCON/RCON live view. For example, CRCON may show a player with many more kills while the page still displays an older count. The killfeed may also appear stale.

Potential causes include stale /api/current-match/players, stale /api/current-match/kills, AdminLog ingestion issues, current-match window filtering, frontend signature/dedupe behavior, browser cache, or a source mismatch between live RCON scoreboard and derived event-based stats.

Files to Read First

  • AGENTS.md
  • ai/architecture-index.md
  • ai/repo-context.md
  • ai/orchestrator/frontend-senior.md
  • ai/orchestrator/backend-senior.md
  • frontend/assets/js/partida-actual.js
  • backend/app/payloads.py
  • backend/app/rcon_admin_log_storage.py
  • backend/app/postgres_rcon_storage.py

Investigation Steps

  1. Repeatedly sample killfeed endpoints for comunidad-hispana-01 and comunidad-hispana-02 with cache busters and no-cache headers.
  2. Repeatedly sample current-match player endpoints for comunidad-hispana-01 and comunidad-hispana-02 with cache busters and no-cache headers.
  3. Audit frontend polling, fetch cache behavior, render signatures, in-flight guards and dedupe logic.
  4. Audit backend payload, storage and query paths for current-match kills and players.
  5. Run read-only DB checks for recent AdminLog events where available.
  6. Inspect local service/container availability and logs where available.
  7. Classify the stale-display cause before applying any staleness fix.
  8. Apply requested visible copy cleanup.
  9. Validate syntax and document the result.

Constraints

  • Do not execute ai-platform run.
  • Do not commit or push.
  • Do not touch physical assets or frontend/assets/img/.
  • Do not touch maps, weapons, clans or brands.
  • Do not change RCON hosts/ports, 27001, or server configuration.
  • Do not reactivate Elo/MMR.
  • Do not reintroduce Comunidad Hispana #03.
  • Do not touch ai/system-metrics.md.
  • Do not include tmp/, TASK-204 or unrelated pending changes.
  • Do not use git add ..
  • Do not introduce technical backend wording into visible UI copy.

Required Copy Changes

  • Remove visible text: Estadisticas derivadas de los eventos recientes.
  • Remove visible text: Mostrando las ultimas 12 bajas detectadas.
  • Replace visible text: Leyendo eventos recientes para esta partida. with Leyendo los enfrentamientos recientes de la partida.

Validation

If frontend changes:

  • node --check frontend/assets/js/partida-actual.js

If backend changes:

  • python -m compileall backend/app
  • cd backend; python -m unittest tests.test_current_match_payload

Functional checks:

  • Repeated endpoint samples identify whether kills and players change over time.
  • Public endpoints return 200 for kills and players on #01 and #02.
  • UI copy no longer contains the removed text.
  • No unrelated pending changes are included.

Findings

Repeated Production Endpoint Samples

All repeated samples used cache busters and no-cache request headers.

Killfeed samples:

  • GET /api/current-match/kills?server=comunidad-hispana-01&limit=18
    • 10 samples over roughly 100 seconds.
    • scope=open-admin-log-match-window.
    • count=0 for all samples.
    • No first/last event id because the endpoint returned no kill rows.
  • GET /api/current-match/kills?server=comunidad-hispana-02&limit=18
    • 10 samples over roughly 100 seconds.
    • scope=open-admin-log-match-window.
    • count=18 for all samples.
    • First event stayed rcon-admin-log:comunidad-hispana-02:4246587.
    • Last event stayed rcon-admin-log:comunidad-hispana-02:4246570.
    • Top rows stayed identical. Top event was Jack -> AleixCommander with SMLE No.1 Mk III.

Player-stat samples:

  • GET /api/current-match/players?server=comunidad-hispana-01
    • 10 samples over roughly 100 seconds.
    • count=1 for all samples.
    • Only visible row stayed Core.D | Axis | K=0 | D=0.
  • GET /api/current-match/players?server=comunidad-hispana-02
    • 10 samples over roughly 100 seconds.
    • count=12 for all samples.
    • Top row stayed Jack | Allies | K=16 | D=6 | SMLE No.1 Mk III.
    • Full single follow-up sample confirmed Jack had kills=16, last_seen_at=2026-06-17T15:34:14.312Z, and source connected,kill,message,team_switch.

Public endpoint status validation:

  • current-match-kills-comunidad-hispana-01: 200.
  • current-match-kills-comunidad-hispana-02: 200.
  • current-match-players-comunidad-hispana-01: 200.
  • current-match-players-comunidad-hispana-02: 200.

Frontend Analysis

  • CURRENT_MATCH_KILL_FEED_POLL_INTERVAL_MS is 1500; killfeed fetch is scheduled every 1.5 seconds.
  • CURRENT_MATCH_PLAYER_STATS_POLL_INTERVAL_MS is 3000; player stats fetch is scheduled every 3 seconds.
  • killFeedRefreshInFlight and playerStatsRefreshInFlight are reset in finally, so normal request failures should not leave either flag stuck.
  • Killfeed rendering consumes data.items directly, filters invalid events, dedupes by event id/semantic key, and renders the latest visible window after TASK-262 style dedupe.
  • Killfeed visible signature includes event/window key, killer/victim names, teams, weapon and teamkill flag.
  • Player stats rendering consumes data.items, dedupes rows, sorts by kills/deaths/name, and renders the table from the current endpoint payload.
  • Player stats visible signature includes player name, team, kills, deaths, teamkills, deaths by teamkill, favorite weapon and last seen.
  • If endpoint data changes in any of those fields, the frontend should re-render.
  • fetchJson currently uses plain fetch(url) and does not set cache: "no-store". The repeated cache-busted production samples still stayed stable, so cache was not proven as the cause in this run.
  • No evidence was found that visibleSignature would block a real kills/stat change from the endpoint.

Backend Analysis

  • /api/current-match/kills is routed in backend/app/routes.py to build_current_match_kill_feed_payload(...).
  • /api/current-match/players is routed in backend/app/routes.py to build_current_match_player_stats_payload(...).
  • Both payload builders read from AdminLog storage through:
    • list_current_match_kill_feed(...)
    • list_current_match_player_stats(...)
  • Neither endpoint queries live RCON directly during the public GET.
  • Killfeed source table is rcon_admin_log_events.
  • Player stat source is also rcon_admin_log_events; it derives kills/deaths/teamkills/favorite weapon by replaying current-window AdminLog events.
  • Current match window is selected from the latest match_start / match_end boundary for the target server.
  • If the latest boundary is match_start, the endpoints use server_time >= open_start_time.
  • If no open match boundary exists, fallback mode uses recent AdminLog rows and filters by freshness.
  • Target matching uses (target_key = ? OR external_server_id = ?), so both target fields are considered for comunidad-hispana-01 and comunidad-hispana-02.

DB / Service Checks

  • Local config reports:
    • use_postgres_rcon_storage=False
    • database_url_set=False
    • storage_path=D:\Proyectos\HLL Vietnam\backend\data\hll_vietnam_dev.sqlite3
    • historical_data_source_kind=rcon
  • Local SQLite schema confirms rcon_admin_log_events stores the current-match event source.
  • Local SQLite data is not production-current:
    • Latest local comunidad-hispana-01 events are from May 20, 2026.
    • Latest local comunidad-hispana-02 events are from May 20, 2026.
    • Production endpoint rows sampled during this task are from June 17, 2026.
  • Local DB max samples repeated after 60 seconds did not change, which only proves local ingestion was not running in this workspace.
  • Docker is not available locally:
    • docker ps --format "{{.Names}}" failed because Docker Desktop/Linux engine is not running.
    • Container logs could not be inspected from this workspace.
  • Production DB/container access was not available from this workspace, so production ingestion status and worker logs could not be directly verified.

Classification

  • During the sample window, both production endpoints were stable. This does not prove a bug by itself because there may have been no new kills/events during the 100-second window.
  • A later real-world check found that the server had changed map and the new match had no kills yet, so /api/current-match/kills returning count=0 in that state is expected and does not prove a bug.
  • The concrete stale-display example described by the user was not reproduced in the sampled state: production players for #02 reported Jack with 16 kills, which is newer than the example of 15 in CRCON and much newer than the stale UI example of 5.
  • The active data source for both current-match feed and player stats is stored AdminLog, not direct live scoreboard state.
  • If CRCON live changes while these endpoints do not, the cause is backend/source-side: AdminLog ingestion, AdminLog query/window filtering, or mismatch between live scoreboard data and derived event data.
  • No evidence was found that frontend visibleSignature/dedupe would ignore changed endpoint values.
  • No backend staleness fix was applied because production DB/log access was unavailable and the current endpoint samples did not prove a specific query/window bug.

Exact Cause

For the stale display reported by the user, the exact confirmed cause is not a frontend render blocker. The current page displays exactly what /api/current-match/kills and /api/current-match/players return, and the render signatures include the fields needed to refresh changed rows.

The most precise verified cause is source-model mismatch and/or AdminLog read-model freshness: current-match player stats are derived from stored AdminLog events, while CRCON live can show direct live scoreboard state. If stored AdminLog ingestion or the current-match AdminLog window lags behind CRCON live, both killfeed and player stats will appear stale even though the frontend polling continues.

Root-cause confirmation still requires a future validation window where CRCON/RCON live shows new kills after a map change and the current-match endpoints can be sampled at the same time.

Changes Applied

  • frontend/partida-actual.html
    • Replaced visible copy:
      • From Leyendo eventos recientes para esta partida.
      • To Leyendo los enfrentamientos recientes de la partida.
  • frontend/assets/js/partida-actual.js
    • Removed the visible feed status/count line when kill rows exist.
    • Removed the visible player-stats line Estadisticas derivadas de los eventos recientes. when stat rows exist.
    • Empty/error states remain visible.

No backend, scheduler, RCON, server configuration, physical asset or image files were changed.

Validation Results

  • Repeated production endpoint sampling for kills #01/#02 and players #01/#02.
  • Public endpoint status checks for kills #01/#02 and players #01/#02 returned 200.
  • Frontend polling/render/signature audit completed.
  • Backend route/payload/storage audit completed.
  • Local SQLite read-only schema/data checks completed.
  • Docker/service log inspection attempted; Docker engine was unavailable locally.
  • node --check frontend/assets/js/partida-actual.js passed.
  • Verified the requested removed/replaced visible text with rg.
  • Reviewed git diff -- frontend/assets/js/partida-actual.js frontend/partida-actual.html.