perf(sim): preload all clips into memory for instant altitude swaps
Each altitude change reset the single <video> element's src and re-fetched the scale's footage over the network, compounded by the dev no-store policy applying to /media too — so every scale change paid a full fetch+decode. - simulator/app.py: split the cache middleware — app shell/JS/CSS stay no-store (by-eye dev iteration), but /media is now cacheable (public, max-age, immutable) since the clips are static. - simulator/static/app.js: preload every ring clip (19 base + 5 transition, ~350 MB) into in-memory blob object URLs at startup — non-blocking, the first scale plays immediately while the rest stream in, ordered current scale outward. mediaUrl() serves the cached blob when ready, else falls back to the network. A small progress chip self-removes when done. - tests: assert app assets stay no-store and /media is cacheable. 269 passed, 2 skipped. Frontend verified by-eye by the operator (no headless browser in repo yet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-5
@@ -234,12 +234,18 @@ def create_app(manifest_path: Optional[Path] = None) -> FastAPI:
|
||||
return {"ok": True, "clip": merged}
|
||||
|
||||
@app.middleware("http")
|
||||
async def _no_cache(request, call_next):
|
||||
# Dev preview server: never let a browser serve a stale app.js/style.css.
|
||||
# The whole point is by-eye iteration, so a plain refresh must always get
|
||||
# the latest assets (the heuristic cache otherwise hides JS/CSS edits).
|
||||
async def _cache_policy(request, call_next):
|
||||
# Dev preview server: never let a browser serve a stale app.js/style.css —
|
||||
# by-eye iteration needs a plain refresh to always get the latest assets.
|
||||
# Media is the exception: the clips are static and large, so they must be
|
||||
# browser-cacheable. The renderer also preloads them into in-memory blob
|
||||
# URLs (static/app.js), but a cacheable header keeps the preload fetch and
|
||||
# any fallback off the network on repeat loads — instant altitude swaps.
|
||||
response = await call_next(request)
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
if request.url.path.startswith("/media/"):
|
||||
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
|
||||
else:
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
return response
|
||||
|
||||
if MEDIA_DIR.exists():
|
||||
|
||||
Reference in New Issue
Block a user