Automate player read model refresh

This commit is contained in:
devRaGonSa
2026-06-09 11:59:31 +02:00
parent 455a712913
commit f341b5510c
6 changed files with 567 additions and 7 deletions

View File

@@ -102,6 +102,19 @@ Refresh policy:
- keep the latest player name seen inside the selected period window
- persist ranking position by kills inside each generated period window
Automatic runner refresh:
- `backend/app/historical_runner.py` refreshes `player_period_stats` automatically
- it inherits the periodic cadence of the historical runner via `HLL_HISTORICAL_REFRESH_INTERVAL_SECONDS`
- the runner executes this step after `player_search_index` and before `ranking_snapshots`
- the public profile path keeps runtime fallback preserved if the read model is empty, incomplete or unavailable
Emergency manual command:
```bash
python -m app.rcon_historical_player_stats refresh-player-period-stats
```
## Public Read Path
Priority for `/api/stats/players/{player_id}`:
@@ -147,7 +160,8 @@ Indexes kept for the public profile flow:
Recommended checks after refresh:
- run `python -m app.rcon_historical_player_stats refresh-player-period-stats`
- confirm the historical runner output reports `player_period_stats_result`
- if an emergency rebuild is needed, run `python -m app.rcon_historical_player_stats refresh-player-period-stats`
- confirm the command reports rows for:
- `all-servers`
- `comunidad-hispana-01`
@@ -162,7 +176,7 @@ Recommended checks after refresh:
## Current Limitations
- periodic refresh is still manual; there is no scheduled operational refresh yet
- the public route still exposes weekly/monthly only; yearly is prepared internally for future use
- runtime fallback remains necessary until production refresh automation is in place
- the runner refreshes all supported public scopes and periods on each cycle even when a manual runner execution is limited with `--server`
- runtime fallback remains necessary as a safety net even with periodic automation in place
- canonical historical truth remains in materialized RCON tables, not in the read model

View File

@@ -71,6 +71,19 @@ Refresh policy:
- keep the latest current-year player name
- store accent-insensitive normalized names in Python
Automatic runner refresh:
- `backend/app/historical_runner.py` refreshes `player_search_index` automatically
- it inherits the periodic cadence of the historical runner via `HLL_HISTORICAL_REFRESH_INTERVAL_SECONDS`
- the runner executes this step after the existing RCON ingestion/materialization cycle
- the runner keeps runtime fallback preserved for the public endpoint
Emergency manual command:
```bash
python -m app.rcon_historical_player_stats refresh-player-search-index
```
## Public Read Path
Priority for `/api/stats/players/search`:
@@ -113,13 +126,15 @@ Search tolerance is implemented with:
- this read model is focused on player search only, not personal profile totals
- counts are current-year only by design
- historical players with no activity in the current UTC year are not intentionally prioritized in this first model
- profile and personal stats still use runtime aggregation over materialized tables
- the runner refreshes all supported public scopes on each cycle even when a manual runner execution is limited with `--server`
- profile and personal stats use their own dedicated read model and still preserve runtime fallback when needed
## Production Validation
Recommended checks after refresh:
- run `python -m app.rcon_historical_player_stats refresh-player-search-index`
- confirm the historical runner output reports `player_search_index_result`
- if an emergency rebuild is needed, run `python -m app.rcon_historical_player_stats refresh-player-search-index`
- confirm the command reports rows for `all-servers`, `comunidad-hispana-01` and `comunidad-hispana-02`
- call `/api/stats/players/search?q=<known-player>&limit=5`
- verify response metadata reports `read_model=player-search-index`

View File

@@ -292,7 +292,12 @@ Supported manual parameters:
Current implementation note:
- `generate-ranking-snapshot` remains unitary per command invocation for explicit manual control
- `refresh-ranking-snapshots --limit 30` generates the full weekly/monthly public matrix in one run
- the periodic historical runner in `backend/app/historical_runner.py` should invoke that bulk refresh as part of the normal backend refresh cycle
- the periodic historical runner in `backend/app/historical_runner.py` invokes that bulk refresh as part of the normal backend refresh cycle
- current cycle order is:
- existing RCON ingestion/materialization cycle
- `player_search_index`
- `player_period_stats`
- `ranking_snapshots`
- per-combination failures should be reported without aborting the entire matrix refresh
## Recommended Combinations
@@ -323,6 +328,8 @@ Operational guidance:
- regenerate after manual backfill
- regenerate after metric SQL changes that affect ranking totals or ordering
- when using the periodic backend runner, keep ranking refresh attached to the same recurring cycle rather than a separate scheduler unless operational load proves otherwise
- the runner inherits its cadence from `HLL_HISTORICAL_REFRESH_INTERVAL_SECONDS`
- fallback runtime remains preserved for `/api/ranking` if a requested snapshot is missing or unavailable
## Ready Vs Fallback