mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 13:53:12 -06:00
A stale bridge must not kill the heartbeat, and rc3 must invalidate the shell
Caught on hardware immediately after deploying rc3 to alpha: the player kept
playing content while reporting nothing at all, throwing every 15 seconds.
Uncaught TypeError: BS.telemetrySnapshot is not a function
The page was rc3 and the bridge it ran was older. Two causes, both fixed.
CACHE_NAME stayed at rd-player-v19 across a release that changed both the
service worker's fetch strategy and the shipped /player assets. The activate
handler deletes every cache whose name does not match, so keeping the name kept
the previous shell cache alive — including a stale st-bridge.js. Bumped to v20.
Content lives in its own cache, so this costs a small shell re-download and never
re-fetches a playlist.
The deeper defect is that the call site treated an optional bridge method as
guaranteed. It was the ONLY unguarded BS.* call in the player; every other one
checks or wraps. The bridge and the page are halves of one contract but are
fetched separately, so version skew is a normal condition, not an anomaly — it
must degrade, not throw. Now guarded on typeof, so a skewed pair reports the
fields it can and keeps heartbeating.
Worth naming the failure shape: the display looked perfectly healthy. Content
played, the socket connected, the device showed online — and telemetry silently
stopped. Anything that reports health through the same path it is breaking will
fail this way.
1056 pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL
This commit is contained in:
parent
3059d8cd5c
commit
7233466030
|
|
@ -1718,7 +1718,11 @@
|
|||
device_utc: Date.now(),
|
||||
// Real values where the platform has them (temperature, storage quota). Spread LAST so
|
||||
// it overrides the nulls above, and empty off-platform so nothing else changes.
|
||||
...(BS ? BS.telemetrySnapshot() : {}),
|
||||
// typeof, not truthiness: the bridge and this page are halves of one contract but are
|
||||
// fetched separately, so a player can run a NEW page against a CACHED older bridge.
|
||||
// Calling a method that version lacks threw here every 15s and took the whole heartbeat
|
||||
// with it — the display kept playing while silently reporting nothing at all.
|
||||
...(BS && typeof BS.telemetrySnapshot === 'function' ? BS.telemetrySnapshot() : {}),
|
||||
}
|
||||
});
|
||||
}, HEARTBEAT_INTERVAL);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
const CACHE_NAME = 'rd-player-v19';
|
||||
// v20: rc3 changed the fetch strategy AND the shipped player assets. The activate handler deletes
|
||||
// every cache whose name does not match, so leaving this at v19 kept the previous shell cache alive
|
||||
// — a player then ran a new index.html against a stale st-bridge.js and threw on every heartbeat.
|
||||
// Bump whenever a shipped /player asset changes shape; content lives in its own cache, so this
|
||||
// costs a small re-download and never re-fetches the playlist.
|
||||
const CACHE_NAME = 'rd-player-v20';
|
||||
// Content lives in its own cache so the shell can be re-versioned (the activate handler deletes
|
||||
// every cache that is not CACHE_NAME) WITHOUT throwing away megabytes of media that are still
|
||||
// perfectly valid. Rolling the shell used to mean a player re-downloaded its entire playlist.
|
||||
|
|
|
|||
Loading…
Reference in a new issue