Observed on a live device, exactly one hour apart:
00:43:43 ERROR plugin football-scoreboard operation timed out after 30.0s
01:43:43 ERROR plugin football-scoreboard operation timed out after 30.0s
One hour is the odds TTL, and that is the whole story. Every game is
cached with the same fixed lifetime, and a slate is fetched in a single
pass, so they all go stale within milliseconds of each other. The next
update then re-fetches the entire card serially -- one ESPN request per
game -- and a normal 5s update runs past the plugin manager's 30s
timeout and is killed part-way through. Whichever games it had not
reached kept no odds until the next cycle, which hit the same wall.
Offset each entry's TTL by up to +-15%, derived from its cache key. An
hour then scatters expiry across about seventeen minutes; over a 16-game
slate the worst 60s window falls from all 16 to a handful.
Deriving the offset from the key rather than drawing it at random is
deliberate. It is stable, so a game keeps its slot across restarts,
where a fresh draw each start would re-cluster the whole slate the first
time the process bounced. It also keeps a random generator out of a path
where nothing is security-sensitive, which is what a scanner flagged.
Deliberately not a change to the fetching itself. Making it concurrent
would also fit inside the timeout, but it multiplies load on ESPN at the
moment of expiry, which is the behaviour that caused this. Spreading the
expiry removes the burst instead of absorbing it.
Four tests on main pinned the TTL as exactly equal to the interval;
they now assert the interval is honoured within the jitter band, keeping
what each was actually about.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5
The 3.2.0 section described the unified sports library but none of the
install-path work that landed in #428 and #431 -- which matters more than a
normal changelog omission, because the sunset rule keys on this section to
tell plugin authors what a given floor buys them.
The headline addition: 3.2.0 is the first release that *enforces*
ledmatrix_min_version. Before it the floor was advisory, so a plugin could
declare one and still be delivered to a core that could not run it. That is
the property B6 waits on, and it is now stated where a plugin author will
look for it -- along with the caveat that a core reporting below 2.0.0 is
treated as unknown rather than old and is never blocked.
Also records compatibility.py (and that it does not yet read
compatible_versions), check_release_version.py and its workflow, the
install-preservation fix, the reentrant-lock deadlock fix, and the
web_interface version re-export.
No version bump: 3.2.0 is unreleased, so this describes the release being
cut rather than a new one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5