fix(signage): bound media cache storage, bandwidth and memory - #519
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
|
CI |
78e0b24 to
c27e200
Compare
- The cache budget comes from navigator.storage.estimate() and persistent storage is requested. Files in the current playlist are never evicted, and a file that cannot fit streams instead. The fixed 512 MB budget evicted files it had just downloaded, so every sync downloaded them again. - A full store (QuotaExceededError or a blob write DataError) evicts, retries once, then streams the file. It retried every 5 minutes. - A failed store read no longer downloads the file again. Replaced, duplicate and empty records are deleted. - Downloads have no overall deadline while data arrives, so large files on slow links can finish. - Downloads stream into a Blob instead of an array of chunks. When the browser cannot build the Blob on small storage, files up to 50 MB retry once in memory and larger files stream. - The sync checks the cache again after its stagger delay. - The service worker no longer stores S3 media a second time.
- Playback and cache syncs share one budget check. Playback never evicts and marks a file too large when storage is full. It allowed a download as large as the whole budget and retried full storage. - Evict before reading a body whose Content-Length needs the room. On a nearly full disk the browser can fail to build a Blob that would fit once older files are gone. - Template backgrounds play from the server when the cache has no copy. They went blank. - Tests: hand the service jsdom's Blob. Before Node 24, Response.blob() returns Node's Blob, which jsdom's File stores as "[object Blob]".
A sync and playback could each work out the free room, download different files, and both store them over the budget. The room is now checked again just before storing, counting entries being stored, and a file claims its size before the store yields. The sync also works out the room again after its stagger delay.
c27e200 to
64745c9
Compare
The offline media cache wasted bandwidth and storage, and could exhaust memory, over long uptime:
QuotaExceededErrorwas retried every 5 min, about 14 GB/day for one 50 MB file.Changes
All in
apps/signage/src/app/media-cache.service.tsandapps/signage/ngsw-config.json:navigator.storage.estimate(), with a 512 MB fallback.navigator.storage.persist()is requested once.media_cache.too_largeand streams during playback, with no 30 s wait.QuotaExceededError, or a blob writeDataError, evicts unneeded files and retries once. If the retry fails, the file streams.TransformStream. On small storage, Chrome can fail to build a Blob over about 20 MB. Files up to 50 MB then retry once in memory, and larger files stream.https://*.amazonaws.com/**/*.*asset group entry is removed.Napkin math for 20 × 50 MB at 4 Mbps:
USER_STORIES.md(US-SIG-025, 026) andDEBUGGING.md(new "Media cache storage" section) are updated.Testing
nx test signagepasses (386 tests).nx build signagepasses.nx lint signagehas 12 errors that are also ondevelop.ngsw.json, and an offline reload plays from the cache.DataError, and 300 MB on 8 GB.Review follow-up
_cacheFit). Playback never evicts, and on full storage it marks the file too large.Content-Lengthneeds the room.Response.blob()returns Node'sBlob. The spec now gives the service jsdom'sBlob. Production is not affected.Known gaps
signage.service.tslogs "Unable to release cached media … not found". This is only log noise.Merge order
Rebased on
developafter #517 and #518 merged. No remaining dependencies.Changes made by Claude Opus 5.5 (1M context) in Claude Code, running in T3 Code.
🤖 Generated with Claude Code