From 9f24b6da7d3ad5aca65756a2a0f054f8747c8f37 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Tue, 28 Apr 2026 11:10:51 +0700 Subject: [PATCH] =?UTF-8?q?chore(pwa):=20tighten=20audio=20cache=20evictio?= =?UTF-8?q?n=20(30d=20=E2=86=92=207d,=20purgeOnQuotaError)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Workbox's CacheFirst rule for /audio/*.mp3 used a 30-day age-based TTL. Approximate LRU by dropping to 7d — a voice clip stays cached as long as it's played at least once a week, otherwise it falls out and re-fetches on next play. Each clip is <200KB and same-origin so the re-fetch cost is negligible. Also flip purgeOnQuotaError so the runtime cache yields first under storage pressure. Default voice precache (vite.config.js additionalManifestEntries) unaffected — it's a separate workbox flow with its own revision. --- .../phase-08-audio-cache-lru.md | 3 ++- plans/260428-0927-implement-todo-backlog/plan.md | 2 +- vite.config.js | 10 +++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plans/260428-0927-implement-todo-backlog/phase-08-audio-cache-lru.md b/plans/260428-0927-implement-todo-backlog/phase-08-audio-cache-lru.md index 850351e..83c2095 100644 --- a/plans/260428-0927-implement-todo-backlog/phase-08-audio-cache-lru.md +++ b/plans/260428-0927-implement-todo-backlog/phase-08-audio-cache-lru.md @@ -1,9 +1,10 @@ --- name: Audio cache LRU rule phase: 8 -status: todo +status: completed priority: low effort: 30m +completed: 2026-04-28 --- # Phase 8 — Audio cache LRU rule diff --git a/plans/260428-0927-implement-todo-backlog/plan.md b/plans/260428-0927-implement-todo-backlog/plan.md index 0e99673..5c93e3d 100644 --- a/plans/260428-0927-implement-todo-backlog/plan.md +++ b/plans/260428-0927-implement-todo-backlog/plan.md @@ -24,7 +24,7 @@ YAGNI — parking-lot features and upstream-blocked items skipped. | 5 | Per-row "Chờ" indicator ✅ | `phase-05-cho-row-indicator.md` | | 6 | Confetti polish (threshold + variety) ✅ | `phase-06-confetti-polish.md` | | 7 | Strict CSP via hashed inline script ✅ | `phase-07-strict-csp-hashed.md` | -| 8 | Audio cache LRU rule | `phase-08-audio-cache-lru.md` | +| 8 | Audio cache LRU rule ✅ | `phase-08-audio-cache-lru.md` | | 9 | PWA install verification checklist | `phase-09-pwa-verify-install.md` | ## Cuts (YAGNI) diff --git a/vite.config.js b/vite.config.js index 416d953..2321917 100644 --- a/vite.config.js +++ b/vite.config.js @@ -61,7 +61,15 @@ export default defineConfig(({ mode }) => { expiration: { // Headroom for future voice growth: 4× current 184 clips. maxEntries: 400, - maxAgeSeconds: 60 * 60 * 24 * 30, + // 7d (was 30d). A clip stays cached as long as it gets + // played at least once a week. Voices that go unused + // for 7d fall out and re-fetch on next play — + // approximates LRU without a custom workbox plugin. + // Each clip <200KB so re-fetch cost is negligible. + maxAgeSeconds: 60 * 60 * 24 * 7, + // Belt-and-suspenders for the rare quota-pressure case + // (lots of voices precached + other origins competing). + purgeOnQuotaError: true, }, // Audio is same-origin → no need to allow opaque (0). cacheableResponse: { statuses: [200] },