fixtures_raw is frozen at server startup while refresh-live refreshes only the bootstrap #17
Labels
No labels
architecture
cleanup
dependencies
performance
priority: high
priority: medium
reliability
security
testing
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
solvreven/FPL#17
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found 2026-08-29 from a user report: the Matches tab showed gameweek 3's
fixtures while nine gameweek 2 matches were being played, and kept showing them
for over an hour of debugging. The code was correct. The data it read was
fetched the previous morning.
/api/refresh-livewas built for exactly this and covers the wrong half.Its own docstring says: "The bootstrap was loaded once at server startup and
never again, so a [stale flag] stayed on screen." It is called by
loadAll()on every page load, so prices, ownership and availability flags are current.
But it sets one key:
fixtures_rawis not in that call. It is written once, bybuild_deps_only()in the startup lifespan, and never again until someone presses the full
/api/refreshbutton (which rebuilds the whole dependency graph and takesminutes). So the fixture list — and every flag on it — is frozen at the moment
the process started.
Those flags are the ones that decide what round it is.
started,finishedandfinished_provisionalflip continuously through a weekend; aboot-time snapshot never does. On the reported day the server had been up since
28.08 09:14, before any GW2 fixture kicked off, so every fixture it heldreported
started: false. Measured directly:What reads the frozen list:
Partially mitigated, deliberately not fixed.
gameweek_in_playnow keys onkickoff_timerather than the flags, because a kickoff time is fixed when thefixture is scheduled and is the one field on the record a stale snapshot cannot
get wrong. That fixes the reported symptom and none of the rest: scorer/assist
prices are still matched against a frozen fixture pairing, and a fixture
rescheduled after boot is invisible until restart.
Suggested fix. Add
fixtures_rawtorefresh_live(). It is one more freeFPL call beside the bootstrap fetch already happening there, on a page load
that already pays for one round trip. If that is judged too eager, give
fixtures_rawan explicit age and refuse to answer "is this round in play"from a snapshot older than it — a stated refusal rather than a confident wrong
answer, which is the pattern this repo uses everywhere else.
Worth recording separately: the symptom was indistinguishable from a code
bug. An hour went into diagnosing it as browser caching, then as a stale
projection cache, then as a stale fixtures snapshot, with three requests to the
user to restart the server. One process listing settled it — a uvicorn started
28.08 09:14:43and never replaced. Check what is RUNNING before theorisingabout what is written; the process list is one command and it is evidence,
where "have you restarted" is a question neither side can verify. (The app also
serves
/static/*through a no-cache middleware, so the hard-refresh advice waswrong on its own terms.)
Related: #13 (no scheduler; every recurring ingest is a manual chore) and #12
(the app reports cache freshness but never its own code version) — the same
shape, an artefact whose age nothing on screen states.
Fixed on
fix/gw2-window-and-provenance(9d9bd4d, pushed just now).backend/web/autorefresh.pyre-fetches bootstrap andfixtures_rawtogether every 300s and applies them in one step, on a daemon thread started in the lifespan. Four properties, each a way an auto-refresher is worse than none, and each with a test:applyis called once or not at all.last_errorandconsecutive_failureson/api/status.age_seconds, None before the first success.The reported symptom is gone: the Matches tab keyed on a snapshot that never updated, so a server started before the first kickoff reported no round in play for the whole round.
gameweek_in_playwas also moved onto the clock rather than only the flags (kickoff_timeis the one field in a fixture record a stale snapshot cannot get wrong), with the flags still sharpening it. Measured both ways after the fix: live fixtures → 2, and the same fixtures with every flag forced False → 2. Before it, the second case returned None.Worth recording for anyone reading this later: the original diagnosis cost an hour because the reader was asked to restart three times while the cause was theorised as caching, then stale deps, then a stale snapshot. One
Get-CimInstance Win32_Processshowed a uvicorn started 28.08 09:14:43 and never replaced — holding code from before every change and a fixtures snapshot from before any GW2 match kicked off. Both symptoms, one fact. Check what is running before theorising about what is written.Closed after PR #19 merged as
6e888a5. The implementation described in the latest issue comment is now on main.