From 8d25f3106d1521303fddf4556918884d797da4b8 Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Tue, 25 Jan 2022 17:00:35 -0500 Subject: [PATCH 1/2] Support for forceSyncFallback --- packages/workbox-background-sync/src/Queue.ts | 31 ++++++++++++++----- .../workbox-background-sync/sw/test-Queue.mjs | 7 +++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/workbox-background-sync/src/Queue.ts b/packages/workbox-background-sync/src/Queue.ts index 97dd895f1..fb8176626 100644 --- a/packages/workbox-background-sync/src/Queue.ts +++ b/packages/workbox-background-sync/src/Queue.ts @@ -27,8 +27,9 @@ interface OnSyncCallback { } export interface QueueOptions { - onSync?: OnSyncCallback; + forceSyncFallback?: boolean; maxRetentionTime?: number; + onSync?: OnSyncCallback; } interface QueueEntry { @@ -81,6 +82,7 @@ class Queue { private readonly _queueStore: QueueStore; private _syncInProgress = false; private _requestsAddedDuringSync = false; + private _forceSyncFallback: boolean; /** * Creates an instance of Queue with the given options @@ -100,8 +102,17 @@ class Queue { * @param {number} [options.maxRetentionTime=7 days] The amount of time (in * minutes) a request may be retried. After this amount of time has * passed, the request will be deleted from the queue. + * @param {boolean} [options.forceSyncFallback=false] If `true`, instead + * of attempting to use background sync events, always attempt to replay + * queued request at service worker startup. Most folks will not need + * this, unless you explicitly target a runtime like Electron that + * exposes the interfaces for background sync, but does not have a working + * implementation. */ - constructor(name: string, {onSync, maxRetentionTime}: QueueOptions = {}) { + constructor( + name: string, + {forceSyncFallback, onSync, maxRetentionTime}: QueueOptions = {}, + ) { // Ensure the store name is not already being used if (queueNames.has(name)) { throw new WorkboxError('duplicate-queue-name', {name}); @@ -112,6 +123,7 @@ class Queue { this._name = name; this._onSync = onSync || this.replayRequests; this._maxRetentionTime = maxRetentionTime || MAX_RETENTION_TIME; + this._forceSyncFallback = Boolean(forceSyncFallback); this._queueStore = new QueueStore(this._name); this._addSyncListener(); @@ -379,7 +391,8 @@ class Queue { * Registers a sync event with a tag unique to this instance. */ async registerSync(): Promise { - if ('sync' in self.registration) { + // See https://github.com/GoogleChrome/workbox/issues/2393 + if ('sync' in self.registration && !this._forceSyncFallback) { try { await self.registration.sync.register(`${TAG_PREFIX}:${this._name}`); } catch (err) { @@ -397,13 +410,14 @@ class Queue { /** * In sync-supporting browsers, this adds a listener for the sync event. - * In non-sync-supporting browsers, this will retry the queue on service - * worker startup. + * In non-sync-supporting browsers, or if _forceSyncFallback is true, this + * will retry the queue on service worker startup. * * @private */ private _addSyncListener() { - if ('sync' in self.registration) { + // See https://github.com/GoogleChrome/workbox/issues/2393 + if ('sync' in self.registration && !this._forceSyncFallback) { self.addEventListener('sync', (event: SyncEvent) => { if (event.tag === `${TAG_PREFIX}:${this._name}`) { if (process.env.NODE_ENV !== 'production') { @@ -450,8 +464,9 @@ class Queue { if (process.env.NODE_ENV !== 'production') { logger.log(`Background sync replaying without background sync event`); } - // If the browser doesn't support background sync, retry - // every time the service worker starts up as a fallback. + // If the browser doesn't support background sync, or the developer has + // opted-in to not using it, retry every time the service worker starts up + // as a fallback. void this._onSync({queue: this}); } } diff --git a/test/workbox-background-sync/sw/test-Queue.mjs b/test/workbox-background-sync/sw/test-Queue.mjs index efa46d066..08ac4ce35 100644 --- a/test/workbox-background-sync/sw/test-Queue.mjs +++ b/test/workbox-background-sync/sw/test-Queue.mjs @@ -205,6 +205,13 @@ describe(`Queue`, function () { expect(onSync.calledOnce).to.be.true; } }); + + it(`should run 'onSync' on instantiation when forceSyncFallback is set`, async function () { + const onSync = sandbox.spy(); + new Queue('foo', {onSync, forceSyncFallback: true}); + + expect(onSync.calledOnce).to.be.true; + }); }); describe(`pushRequest`, function () { From 16ba0e5d31b7111b9aaf76c213c203f071aaa8f1 Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Tue, 25 Jan 2022 17:24:40 -0500 Subject: [PATCH 2/2] Linting --- packages/workbox-background-sync/src/Queue.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workbox-background-sync/src/Queue.ts b/packages/workbox-background-sync/src/Queue.ts index fb8176626..4e0518396 100644 --- a/packages/workbox-background-sync/src/Queue.ts +++ b/packages/workbox-background-sync/src/Queue.ts @@ -80,9 +80,9 @@ class Queue { private readonly _onSync: OnSyncCallback; private readonly _maxRetentionTime: number; private readonly _queueStore: QueueStore; + private readonly _forceSyncFallback: boolean; private _syncInProgress = false; private _requestsAddedDuringSync = false; - private _forceSyncFallback: boolean; /** * Creates an instance of Queue with the given options