170 lines
5.7 KiB
Markdown
170 lines
5.7 KiB
Markdown
# Public Snapshot Refresh Schedule
|
|
|
|
## Goal
|
|
|
|
Public pages must read persisted snapshots and read models only. No public GET endpoint should regenerate ranking or historical snapshots at request time.
|
|
|
|
## Current Scheduler Owner
|
|
|
|
The internal `historical-runner` owns public refresh scheduling. Host cron is not required.
|
|
|
|
## Implemented Cadence
|
|
|
|
Local timezone for scheduled jobs: `Europe/Madrid`.
|
|
|
|
Heavy daily window:
|
|
|
|
- full public refresh:
|
|
- `06:00`
|
|
- rebuilds full historical snapshots, weekly/monthly ranking snapshots, annual ranking snapshots, player search index and player period stats
|
|
- runs under `public-full-refresh`
|
|
|
|
Ranking page:
|
|
|
|
- annual ranking:
|
|
- rebuilt inside the daily full refresh at `06:00`
|
|
- generated sequentially per scope and metric
|
|
- monthly ranking:
|
|
- `07:00` and `19:00`
|
|
- generated sequentially per scope and metric
|
|
- runs under `public-ranking-monthly-refresh`
|
|
- weekly ranking:
|
|
- every hour at minute `10`
|
|
- generated sequentially per scope and metric
|
|
- runs under `public-ranking-weekly-refresh`
|
|
|
|
Historical page:
|
|
|
|
- weekly historical leaderboard subset:
|
|
- every hour at minute `25`
|
|
- scopes:
|
|
- `all-servers`
|
|
- `comunidad-hispana-01`
|
|
- `comunidad-hispana-02`
|
|
- metrics:
|
|
- `kills`
|
|
- `deaths`
|
|
- `matches_over_100_kills`
|
|
- `support`
|
|
- runs under `public-historical-weekly-refresh`
|
|
- monthly historical UI subset:
|
|
- every `2` hours at minute `40`
|
|
- same scopes as weekly historical
|
|
- leaderboard metrics:
|
|
- `kills`
|
|
- `deaths`
|
|
- `matches_over_100_kills`
|
|
- `support`
|
|
- also refreshes:
|
|
- `monthly-mvp`
|
|
- `monthly-mvp-v2`
|
|
- runs under `public-historical-monthly-refresh`
|
|
|
|
Recent matches:
|
|
|
|
- interval polling fallback remains enabled through `HLL_PUBLIC_RECENT_MATCHES_REFRESH_INTERVAL_SECONDS`
|
|
- default: `60` seconds
|
|
- immediate refresh still happens when the RCON capture loop materializes a finished match
|
|
|
|
## Why Historical Weekly And Monthly Were Missing
|
|
|
|
The previous short cadence only refreshed:
|
|
|
|
- `ranking_snapshots` for `/api/ranking`
|
|
- `recent-matches` snapshots
|
|
|
|
It did not refresh the broader historical snapshot subset consumed by `historico.html`. That left weekly and monthly historical leaderboard payloads in `snapshot_status=missing` until the next daily full refresh.
|
|
|
|
## Locking And Overlap Policy
|
|
|
|
The scheduler uses in-process locks and controlled skips. It does not enqueue backlog jobs.
|
|
|
|
Heavy jobs:
|
|
|
|
- `public-full-refresh`
|
|
- `public-ranking-annual-refresh`
|
|
- `public-ranking-monthly-refresh`
|
|
|
|
Policy:
|
|
|
|
- heavy jobs do not overlap with other heavy jobs
|
|
- hourly and bi-hourly jobs skip when a conflicting heavy job is in progress
|
|
- if a heavy job already ran in the same scheduler tick, lower-priority jobs skip and retry on the next tick
|
|
- weekly and monthly historical subset jobs also avoid overlapping with each other
|
|
|
|
This keeps the implementation simple and avoids CPU spikes without reintroducing request-time fallback work.
|
|
|
|
## Last Update Exposure
|
|
|
|
Historical and ranking payloads continue to expose persisted generation metadata from the snapshot records:
|
|
|
|
- `snapshot_status`
|
|
- `generated_at`
|
|
- `source_range_start`
|
|
- `source_range_end`
|
|
- `is_stale`
|
|
|
|
`historico.js` already renders `generated_at` as the visible "Actualizado" label, so no frontend contract change was required for this task.
|
|
|
|
## Environment Variables
|
|
|
|
Existing variables kept:
|
|
|
|
- `HLL_PUBLIC_FULL_REFRESH_ENABLED`
|
|
- `HLL_PUBLIC_FULL_REFRESH_TIME`
|
|
- `HLL_PUBLIC_FULL_REFRESH_TIMEZONE`
|
|
- `HLL_PUBLIC_RECENT_MATCHES_REFRESH_INTERVAL_SECONDS`
|
|
|
|
Retained for compatibility:
|
|
|
|
- `HLL_PUBLIC_RANKING_REFRESH_INTERVAL_SECONDS`
|
|
- no longer drives the hourly/slot-based ranking scheduler
|
|
- still participates in runner tick resolution and legacy compatibility paths
|
|
|
|
New scheduler variables:
|
|
|
|
- `HLL_PUBLIC_RANKING_WEEKLY_REFRESH_MINUTE`
|
|
- default `10`
|
|
- `HLL_PUBLIC_RANKING_MONTHLY_REFRESH_TIMES`
|
|
- default `07:00,19:00`
|
|
- `HLL_PUBLIC_HISTORICAL_WEEKLY_REFRESH_MINUTE`
|
|
- default `25`
|
|
- `HLL_PUBLIC_HISTORICAL_MONTHLY_REFRESH_MINUTE`
|
|
- default `40`
|
|
- `HLL_PUBLIC_HISTORICAL_MONTHLY_REFRESH_HOUR_INTERVAL`
|
|
- default `2`
|
|
|
|
## Manual Validation Commands
|
|
|
|
One-off public jobs through the runner:
|
|
|
|
```powershell
|
|
docker compose exec historical-runner python -m app.historical_runner --public-job ranking-weekly
|
|
docker compose exec historical-runner python -m app.historical_runner --public-job ranking-monthly
|
|
docker compose exec historical-runner python -m app.historical_runner --public-job historical-weekly
|
|
docker compose exec historical-runner python -m app.historical_runner --public-job historical-monthly
|
|
docker compose exec historical-runner python -m app.historical_runner --public-job public-full
|
|
```
|
|
|
|
Direct ranking matrix commands:
|
|
|
|
```powershell
|
|
docker compose exec historical-runner python -m app.rcon_historical_leaderboards refresh-ranking-snapshots --timeframe weekly --limit 30
|
|
docker compose exec historical-runner python -m app.rcon_historical_leaderboards refresh-ranking-snapshots --timeframe monthly --limit 30
|
|
```
|
|
|
|
Operational checks:
|
|
|
|
```powershell
|
|
docker logs --tail=300 hll-vietnam-historical-runner-1
|
|
docker exec hll-vietnam-historical-runner-1 sh -lc 'env | sort | grep HLL_PUBLIC'
|
|
python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter servers --output tmp\task240_servers_after.json
|
|
python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --output tmp\task240_full_audit_after.json
|
|
```
|
|
|
|
UI checks:
|
|
|
|
- verify `historico.html` weekly rankings render without `snapshot_status=missing`
|
|
- verify `historico.html` monthly rankings render without `snapshot_status=missing`
|
|
- verify the visible "Actualizado" label changes after the corresponding runner job
|