7.2 KiB
id, title, status, type, team, supporting_teams, roadmap_item, priority
| id | title | status | type | team | supporting_teams | roadmap_item | priority |
|---|---|---|---|---|---|---|---|
| TASK-227 | Fix current-match kills and players timeouts | done | backend | Backend Senior | foundation | high |
TASK-227 - Fix current-match kills and players timeouts
Goal
Corregir especificamente los endpoints publicos secundarios de partida actual que seguian bloqueando tras TASK-226:
/api/current-match/kills/api/current-match/players
El objetivo no es reconectar RCON ni cambiar configuracion, sino evitar que estos endpoints publicos entren en inicializacion o lecturas bloqueantes y asegurar degradacion JSON controlada cuando el read model no este disponible.
Context
Validacion real tras TASK-226 contra produccion:
python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp\task226_current_match_audit_after.json
Resultados relevantes:
current-match-comunidad-hispana-01: OK 200, 2314 ms.current-match-kills-comunidad-hispana-01: CRITICAL, timeout 30026 ms.current-match-players-comunidad-hispana-01: CRITICAL, timeout 30079 ms.current-match-comunidad-hispana-02: OK 200, 2265 ms.current-match-kills-comunidad-hispana-02: CRITICAL, timeout 30050 ms.current-match-players-comunidad-hispana-02: CRITICAL, 200 pero 26095 ms,fallback=True.
Tambien se valido que /api/servers ya esta OK en unos 82 ms y que TASK-225 sigue OK para player search/profile y historical match detail. Esta task no toca esas rutas.
Files Read First
ai/architecture-index.mdai/repo-context.mdai/orchestrator/backend-senior.mdbackend/README.mdbackend/app/routes.pybackend/app/payloads.pybackend/app/rcon_admin_log_storage.pybackend/app/postgres_rcon_storage.pybackend/tests/test_current_match_payload.py
Call Chain Analysis
Rutas exactas en backend/app/routes.py:
/api/current-match/killsvalidaserver,limit,since_event_idy llamabuild_current_match_kill_feed_payload(server_slug=..., limit=..., since_event_id=...)./api/current-match/playersvalidaservery llamabuild_current_match_player_stats_payload(server_slug=...)./api/current-matchgeneral llamabuild_current_match_payload(server_slug=...).
Cadena del endpoint general:
resolve_get_payload("/api/current-match?...")build_current_match_payload()_query_current_match_rcon_sample()intenta una muestra RCON de sesion.- Si falla, cae a
build_servers_payload(). - Tras
TASK-226,build_servers_payload()es cache/snapshot-only y no refresca RCON/A2S en el GET publico.
Cadena de kills:
resolve_get_payload("/api/current-match/kills?...")build_current_match_kill_feed_payload()list_current_match_kill_feed(server_key=origin.slug, ensure_storage=False)- En PostgreSQL, el codigo llamaba
connect_postgres_compat()sin argumentos. connect_postgres_compat()tieneinitialize=Truepor defecto.initialize_postgres_rcon_storage()ejecutaba bootstrap/DDL antes de abrir la lectura.
Cadena de players:
resolve_get_payload("/api/current-match/players?...")build_current_match_player_stats_payload()list_current_match_player_stats(server_key=origin.slug, ensure_storage=False)- En PostgreSQL, el codigo llamaba
connect_postgres_compat()sin argumentos. connect_postgres_compat()inicializaba storage por defecto igual que kills.
Root Cause
TASK-226 paso ensure_storage=False desde los payloads publicos, pero en la rama PostgreSQL de backend/app/rcon_admin_log_storage.py ese flag no se propagaba a connect_postgres_compat().
Resultado: en produccion con HLL_BACKEND_DATABASE_URL, kills/players seguian ejecutando initialize_postgres_rcon_storage() durante el GET publico. Esa inicializacion/DDL en el request path explica la diferencia frente a /api/current-match general: el endpoint general no pasa por AdminLog ni por connect_postgres_compat() para construir kills/players; usa muestra RCON de sesion y fallback a snapshot de servidores.
No se encontro necesidad de cambiar hosts RCON, puertos, 27001, 127.0.0.1, variables de entorno ni configuracion de servidores.
Changes
backend/app/rcon_admin_log_storage.pylist_current_match_kill_feed()ahora llamaconnect_postgres_compat(initialize=ensure_storage).list_current_match_player_stats()ahora llamaconnect_postgres_compat(initialize=ensure_storage).- Con
ensure_storage=False, las lecturas publicas de AdminLog no inicializan PostgreSQL.
backend/tests/test_current_match_payload.py- Anade tests de regresion para kills y players verificando que la ruta PostgreSQL read-only llama
connect_postgres_compat(initialize=False).
- Anade tests de regresion para kills y players verificando que la ruta PostgreSQL read-only llama
docs/FULL_APPLICATION_REQUEST_AUDIT.md- Documenta el estado post-fix de
TASK-227.
- Documenta el estado post-fix de
docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md- Actualiza la nota de arquitectura de lectura publica para reflejar la correccion real de PostgreSQL read-only.
Validation
Validaciones ejecutadas:
python -m compileall backend/app
cd backend
python -m unittest tests.test_current_match_payload
cd backend
python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh
Resultados:
python -m compileall backend/app: OK.cd backend; python -m unittest tests.test_current_match_payload: OK, 5 tests.cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh: OK, 18 tests.
Auditoria HTTP local:
- No se ejecuto auditoria local porque
http://127.0.0.1:8000/healthno respondio desde el host.
Comando exacto para validar produccion tras redeploy:
python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp\task227_current_match_audit_after.json
Outcome
La ruta publica secundaria de AdminLog queda realmente read-only en PostgreSQL cuando los payloads llaman con ensure_storage=False. Si el read model no existe o falla, los payloads ya capturan la excepcion y devuelven status: ok, items: [], fallback_used: true y fallback_reason controlado, sin 500 vacio.
Constraints Confirmed
- No se cambio
27001. - No se cambiaron hosts ni puertos RCON.
- No se cambio
127.0.0.1. - No se cambiaron variables de entorno de servidores.
- No se cambio configuracion de servidores.
- No se toco
/api/servers. - No se tocaron player search/profile/historical detail.
- No se reactivo Elo/MMR.
- No se reintrodujo Comunidad Hispana #03.
- No se toco frontend.
- No se tocaron assets, SVGs ni imagenes fisicas.
- No se toco
frontend/assets/img/weapons/. - No se toco
frontend/assets/img/clans/. - No se toco
ai/system-metrics.md. - No se incluyo
tmp/.
Risks
- Si PostgreSQL esta caido o la apertura de conexion queda bloqueada por red/DNS, el endpoint aun depende del timeout de conexion de PostgreSQL. Esta task elimina el bootstrap/DDL publico identificado, no introduce cambios de configuracion ni pooling.
/api/current-matchgeneral sigue con muestra RCON directa por diseno actual; no fue parte de esta task porque la auditoria post-226 lo midio OK en unos 2.3 s.- La confirmacion final de latencia requiere redeploy y auditoria de produccion.