mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-03 00:13:09 +00:00
fix: keep the old build's offline files from coming back after a deploy #523
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { FakeCaches, loadWorker } from './sw-harness';
|
||||
|
||||
const settle = () => new Promise((r) => setTimeout(r, 0));
|
||||
|
||||
// The service worker names its caches after the build it came with (#523)
|
||||
// and deletes a build's cache once no open tab runs that build.
|
||||
describe('service worker caches per build', () => {
|
||||
@@ -45,4 +47,32 @@ describe('service worker caches per build', () => {
|
||||
await worker.dispatch('message', { data: { type: 'skip-waiting' } });
|
||||
expect(worker.skipped()).toBe(before + 1);
|
||||
});
|
||||
|
||||
it("the old build's worker doesn't bring back its cache after the new build deleted it", async () => {
|
||||
const caches = new FakeCaches();
|
||||
const state = await caches.open('bulwark-sw-state-v1');
|
||||
await state.put('/__bulwark/offline-shell', new Response(JSON.stringify({ on: true })));
|
||||
let online = true;
|
||||
// The server runs build b now and says so on every answer.
|
||||
const fetchFromB = async () => {
|
||||
if (!online) throw new TypeError('Failed to fetch');
|
||||
const res = new Response('{}', { status: 200, headers: { 'Content-Type': 'application/json', 'X-Bulwark-Build': 'b' } });
|
||||
Object.defineProperty(res, 'type', { value: 'basic' });
|
||||
return res;
|
||||
};
|
||||
const old = loadWorker({ buildId: 'a', caches, clients: [], fetch: fetchFromB });
|
||||
await settle();
|
||||
// Build b's worker took over and deleted build a's files, while the
|
||||
// reloaded tab's first requests still went through build a's worker.
|
||||
expect(await caches.has('bulwark-shell-a')).toBe(false);
|
||||
await old.request({ url: 'https://mail.example.com/api/config' });
|
||||
await settle();
|
||||
expect(await caches.has('bulwark-shell-a')).toBe(false);
|
||||
expect(await caches.has('bulwark-shell-b')).toBe(true);
|
||||
|
||||
online = false;
|
||||
await old.request({ url: 'https://mail.example.com/mail', mode: 'navigate' }).catch(() => null);
|
||||
await settle();
|
||||
expect(await caches.has('bulwark-shell-a')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
+11
-5
@@ -139,10 +139,14 @@ async function cachedDocument(url) {
|
||||
const path = appPagePath(url) || "/";
|
||||
const section = "/" + (path.split("/").filter(Boolean)[0] || "");
|
||||
const candidates = [documentKey(url), self.location.origin + BASE_PATH + (section === "/" ? "" : section), self.location.origin + BASE_PATH];
|
||||
const own = await caches.open(SHELL_CACHE);
|
||||
for (const key of candidates) {
|
||||
const hit = await own.match(key);
|
||||
if (hit) return hit;
|
||||
// Only looked into when it exists: opening it would create it again
|
||||
// after the next build's worker deleted it.
|
||||
if (await caches.has(SHELL_CACHE)) {
|
||||
const own = await caches.open(SHELL_CACHE);
|
||||
for (const key of candidates) {
|
||||
const hit = await own.match(key);
|
||||
if (hit) return hit;
|
||||
}
|
||||
}
|
||||
for (const key of candidates) {
|
||||
const hit = await caches.match(key);
|
||||
@@ -195,7 +199,9 @@ async function respondWithConfig(request) {
|
||||
const response = await fetch(request);
|
||||
if (response.ok) {
|
||||
const copy = response.clone();
|
||||
caches.open(SHELL_CACHE).then((cache) => cache.put(key, copy)).catch(() => {});
|
||||
// Like pages and chunks, under the build that answered: right after a
|
||||
// deploy this worker still fetches for the new build's tab.
|
||||
caches.open(shellCacheFor(response)).then((cache) => cache.put(key, copy)).catch(() => {});
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user