fix(sim): revalidate /media instead of pinning it immutable

The `immutable, max-age=1y` media header pinned stale footage in the browser for
a year, so a re-sourced or re-cropped clip (e.g. the de-captioned cosmos) never
showed without a manual cache clear. Switch /media to `no-cache` (store, but
revalidate every load): instant altitude swaps already come from the in-memory
blob preload, so the HTTP cache only matters on (re)load — where a conditional
request is a cheap 304 when unchanged but picks up edited clips immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BenStullsBets
2026-06-25 09:20:14 -07:00
parent 53cb89b4c6
commit a2ef792f0f
2 changed files with 11 additions and 6 deletions
+7 -5
View File
@@ -237,13 +237,15 @@ def create_app(manifest_path: Optional[Path] = None) -> FastAPI:
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.
# Media uses `no-cache` (store, but REVALIDATE every load): instant altitude
# swaps already come from the in-memory blob preload (static/app.js), so the
# HTTP cache only matters on (re)load — where a conditional request returns a
# cheap 304 when unchanged, yet picks up a re-sourced/re-cropped clip
# immediately. `immutable` was wrong here: it pinned stale footage for a year
# so edited clips never showed without a manual cache clear.
response = await call_next(request)
if request.url.path.startswith("/media/"):
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
response.headers["Cache-Control"] = "no-cache"
else:
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
return response
+4 -1
View File
@@ -113,8 +113,11 @@ def test_media_is_cacheable(tmp_path, monkeypatch):
resp = client.get("/media/cosmos/base.mp4")
assert resp.status_code == 200
cc = resp.headers.get("cache-control", "")
# Stored but revalidated: not no-store (so the blob preload can cache it), and
# not pinned immutable (so a re-sourced/re-cropped clip shows on a plain reload).
assert "no-store" not in cc
assert "max-age" in cc
assert "immutable" not in cc
assert "no-cache" in cc
@pytest.fixture