From e11149ed5749a8b1b7672e640d47c04e2a4732d6 Mon Sep 17 00:00:00 2001 From: Barack Sokullu Date: Sat, 15 Aug 2026 04:02:35 +0300 Subject: [PATCH] Rearm Apocalypse downloads after cancellation --- dist/webbrain-chrome-32.0.0.zip | Bin 16291813 -> 16291813 bytes dist/webbrain-edge-32.0.0.zip | Bin 16291813 -> 16291813 bytes dist/webbrain-firefox-32.0.0.zip | Bin 3213151 -> 3213151 bytes src/chrome/src/agent/apocalypse-mode.js | 27 +++++++++--- src/firefox/src/agent/apocalypse-mode.js | 27 +++++++++--- test/run.js | 54 +++++++++++++++++++++++ 6 files changed, 94 insertions(+), 14 deletions(-) diff --git a/dist/webbrain-chrome-32.0.0.zip b/dist/webbrain-chrome-32.0.0.zip index e36b21f43184386a1df9892edf3c457a1459c94f..7c9f4fec9fe045196dcdf4198b446b25e467af9d 100644 GIT binary patch delta 17984 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 delta 17984 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 diff --git a/dist/webbrain-edge-32.0.0.zip b/dist/webbrain-edge-32.0.0.zip index c90484e965df1f1fd1ecd3e1a99d021be834c0e1..ea56de7c0d70d3267a9c553f3f675a1b0d941e9c 100644 GIT binary patch delta 17984 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 delta 17984 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 diff --git a/dist/webbrain-firefox-32.0.0.zip b/dist/webbrain-firefox-32.0.0.zip index 985ca874442c2d309649c6d5fa17674dbe38dd80..2c88ef4d8bb1df93b87e09210a8ab501d3bd5b54 100644 GIT binary patch delta 15189 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 Sqq))C8To%ITewb?SN{h-M*jr> delta 15189 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 {}); if (!current) await storage.remove(record.target, record).catch(() => {}); - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } const bytesDownloaded = offset + bytes.byteLength; const finished = bytesDownloaded >= Number(record.size); @@ -1082,7 +1095,7 @@ export function createApocalypseArchiveManager(options = {}) { if (writeSessionCommitted && !await store.getArchive(record.id)) { await storage.remove(record.target, record).catch(() => {}); } - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } piecesProcessed += 1; if (continueInWake) { @@ -1098,7 +1111,7 @@ export function createApocalypseArchiveManager(options = {}) { const current = await store.getArchive(record.id); if (!current || current.generation !== generation || current.leaseToken !== leaseToken || controller.signal.aborted) { if (!current && writeSessionCommitted) await storage.remove(record.target, record).catch(() => {}); - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } const rollbackWriteSession = current.writeSessionStartPiece != null && !writeSessionCommitted; const permissionRequired = isFilePermissionError(error, current.target); @@ -1128,7 +1141,7 @@ export function createApocalypseArchiveManager(options = {}) { const saved = await putArchiveIfCurrent(store, next, { status: 'downloading', generation, leaseToken, updatedAt: current.updatedAt, }); - if (!saved) return { processed: false, reason: 'cancelled' }; + if (!saved) return await cancelledResult(); const nextDelay = nextArchiveScheduleDelay(await store.listArchives(), now()); if (nextDelay != null) schedule(nextDelay); return { processed: false, reason: retrying ? 'retrying' : 'error', archive: next }; diff --git a/src/firefox/src/agent/apocalypse-mode.js b/src/firefox/src/agent/apocalypse-mode.js index 146519e92..25a2b97c1 100644 --- a/src/firefox/src/agent/apocalypse-mode.js +++ b/src/firefox/src/agent/apocalypse-mode.js @@ -822,6 +822,19 @@ export function createApocalypseArchiveManager(options = {}) { let processing = false; if (!store || !storage) throw new Error('Apocalypse Mode requires state and archive storage adapters.'); + async function cancelledResult() { + try { + const config = await store.getConfig(); + if (config?.enabled === true) { + const nextDelay = nextArchiveScheduleDelay(await store.listArchives(), now()); + if (nextDelay != null) schedule(nextDelay); + } + } catch { + // Preserve the cancellation result if rearming the shared alarm fails. + } + return { processed: false, reason: 'cancelled' }; + } + async function getSnapshot() { const [config, archives] = await Promise.all([store.getConfig(), store.listArchives()]); return { @@ -973,7 +986,7 @@ export function createApocalypseArchiveManager(options = {}) { const saved = await putArchiveIfCurrent(store, recovered, { status: 'downloading', generation, leaseToken, updatedAt: record.updatedAt, }); - if (!saved) return { processed: false, reason: 'cancelled' }; + if (!saved) return await cancelledResult(); record = recovered; } let writer = null; @@ -1006,7 +1019,7 @@ export function createApocalypseArchiveManager(options = {}) { const saved = await putArchiveIfCurrent(store, marked, { status: 'downloading', generation, leaseToken, updatedAt: record.updatedAt, }); - if (!saved) return { processed: false, reason: 'cancelled' }; + if (!saved) return await cancelledResult(); record = marked; writer = await storage.createWriter(record.target, record); usedWriteSession = true; @@ -1033,7 +1046,7 @@ export function createApocalypseArchiveManager(options = {}) { let current = await store.getArchive(record.id); let currentConfig = await store.getConfig(); if (!ownsDownloadClaim(current, generation, leaseToken, currentConfig)) { - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } if (writer) await writer.write(offset, bytes); else await storage.write(record.target, offset, bytes, record); @@ -1042,7 +1055,7 @@ export function createApocalypseArchiveManager(options = {}) { if (!ownsDownloadClaim(current, generation, leaseToken, currentConfig)) { await abortWriteSession(new Error('Archive download was cancelled.')).catch(() => {}); if (!current) await storage.remove(record.target, record).catch(() => {}); - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } const bytesDownloaded = offset + bytes.byteLength; const finished = bytesDownloaded >= Number(record.size); @@ -1082,7 +1095,7 @@ export function createApocalypseArchiveManager(options = {}) { if (writeSessionCommitted && !await store.getArchive(record.id)) { await storage.remove(record.target, record).catch(() => {}); } - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } piecesProcessed += 1; if (continueInWake) { @@ -1098,7 +1111,7 @@ export function createApocalypseArchiveManager(options = {}) { const current = await store.getArchive(record.id); if (!current || current.generation !== generation || current.leaseToken !== leaseToken || controller.signal.aborted) { if (!current && writeSessionCommitted) await storage.remove(record.target, record).catch(() => {}); - return { processed: false, reason: 'cancelled' }; + return await cancelledResult(); } const rollbackWriteSession = current.writeSessionStartPiece != null && !writeSessionCommitted; const permissionRequired = isFilePermissionError(error, current.target); @@ -1128,7 +1141,7 @@ export function createApocalypseArchiveManager(options = {}) { const saved = await putArchiveIfCurrent(store, next, { status: 'downloading', generation, leaseToken, updatedAt: current.updatedAt, }); - if (!saved) return { processed: false, reason: 'cancelled' }; + if (!saved) return await cancelledResult(); const nextDelay = nextArchiveScheduleDelay(await store.listArchives(), now()); if (nextDelay != null) schedule(nextDelay); return { processed: false, reason: retrying ? 'retrying' : 'error', archive: next }; diff --git a/test/run.js b/test/run.js index f27a5b76f..c9cd8978e 100644 --- a/test/run.js +++ b/test/run.js @@ -21366,6 +21366,60 @@ test('Apocalypse Mode requires opt-in and removal wins an in-flight download rac } }); +test('Apocalypse Mode rearms queued work after pausing or deleting the active download', async () => { + for (const [label, runtime] of [['chrome', ApocalypseModeCh], ['firefox', ApocalypseModeFx]]) { + for (const action of ['pause', 'remove']) { + const active = { + id: `${action}-active`, status: 'queued', generation: 1, updatedAt: 100, + filename: 'active.zim', size: 1, pieceLength: 1, pieceHashAlgorithm: 'sha-1', pieceHashes: ['aa'], + downloadUrl: 'https://example.test/active.zim', target: { kind: 'opfs', key: 'active.zim' }, + pieceIndex: 0, bytesDownloaded: 0, retryCount: 0, + }; + const queued = { + ...active, + id: `${action}-queued`, + filename: 'queued.zim', + downloadUrl: 'https://example.test/queued.zim', + target: { kind: 'opfs', key: 'queued.zim' }, + }; + const records = new Map([[active.id, active], [queued.id, queued]]); + const store = { + async getConfig() { return { enabled: true }; }, + async listArchives() { return [...records.values()].map(record => ({ ...record })); }, + async getArchive(id) { const record = records.get(id); return record ? { ...record } : null; }, + async putArchive(record) { records.set(record.id, { ...record }); return record; }, + async deleteArchive(id) { records.delete(id); }, + }; + let markFetchStarted; + const fetchStarted = new Promise(resolve => { markFetchStarted = resolve; }); + const scheduled = []; + const manager = runtime.createApocalypseArchiveManager({ + store, + storage: { async remove() {} }, + fetchImpl: async (_url, request) => await new Promise((_resolve, reject) => { + request.signal.addEventListener('abort', () => reject(new DOMException('cancelled', 'AbortError')), { once: true }); + markFetchStarted(); + }), + digestHex: async () => 'aa', + schedule: delay => scheduled.push(delay), + randomId: () => `${action}-lease`, + now: () => 1000, + }); + + const running = manager.processNext(); + await fetchStarted; + await manager[action](active.id); + const result = await running; + + assert.equal(result.reason, 'cancelled', `${label}: ${action} did not cancel the active download`); + assert.deepEqual(scheduled, [0], `${label}: ${action} stranded the next queued archive`); + assert.equal(records.get(queued.id)?.status, 'queued', `${label}: ${action} changed the next archive state`); + if (action === 'pause') assert.equal(records.get(active.id)?.status, 'paused', `${label}: pause state was lost`); + else assert.equal(records.has(active.id), false, `${label}: removed active archive metadata was retained`); + } + } +}); + test('Apocalypse Mode disabling loses atomically to concurrent archive deletion', async () => { for (const [label, runtime] of [['chrome', ApocalypseModeCh], ['firefox', ApocalypseModeFx]]) { const config = { enabled: true, updatePolicy: 'manual' };