workbox
workbox copied to clipboard
workbox-background-sync/Queue replayRequests change order of request`s
Library Affected: workbox-background-sync
Browser & Platform: Caught on a Mobile Chrome, but can thrown on any.
Issue or Feature Request Description: Queue.replayRequests operation don't block queue storage for adding new request. That can throw switch place of first two request.
Screenshots:
For replying issue need in time that replayRequests executed push new request. (In my case thrown by 2 inline request).
Code of my service worker:
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
import { registerRoute, NavigationRoute } from 'workbox-routing';
import { skipWaiting, clientsClaim } from 'workbox-core';
import { CacheFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';
import { IgnoreURLParameterPlugin } from './workbox-plugins';
import { Queue } from 'workbox-background-sync';
import * as Messenger from '../src/redux/reducers/util/Messenger';
declare const self: Window & ServiceWorkerGlobalScope & WorkerGlobalScope;
skipWaiting();
clientsClaim();
precacheAndRoute(self.__WB_MANIFEST);
registerRoute(
({ url }) => url.origin.includes('s3.amazonaws.com') && !url.pathname.includes('.pdf'),
new CacheFirst({
cacheName: 'image-cache',
plugins: [
new CacheableResponsePlugin({
statuses: [200],
}),
new IgnoreURLParameterPlugin(),
new ExpirationPlugin({
maxEntries: 2000,
maxAgeSeconds: 3 * 24 * 60 * 60,
}),
],
}),
'GET'
);
const handler = createHandlerBoundToURL('/index.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);
const queue = new Queue('requestsQueue', {
maxRetentionTime: 3 * 24 * 60,
onSync: async (event): Promise<void> => {
try {
await event.queue.replayRequests();
} finally {
Messenger.sendMessage<number>('requests_queue_length', (await event.queue.getAll()).length);
}
},
});
async function sendRequestsQueueLength(): Promise<void> {
Messenger.sendMessage<number>('requests_queue_length', (await queue.getAll()).length);
}
const replayRequestsQueue = async (): Promise<void> => {
try {
await queue.replayRequests();
} finally {
await sendRequestsQueueLength();
}
};
Messenger.createMessageListener<null>('replay_requests_queue', () => {
replayRequestsQueue();
});
const processRequest = async (request: Request): Promise<Response> => {
const isQueueEmpty = (await queue.getAll()).length === 0;
if (isQueueEmpty) {
try {
return await fetch(request.clone());
} catch {} // eslint-disable-line no-empty
}
await queue.pushRequest({ request });
replayRequestsQueue();
return new Response(null, { status: 200 });
};
self.addEventListener('online', () => {
replayRequestsQueue();
});
self.addEventListener('fetch', (event: FetchEvent) => {
if (
!event.request.url.includes('yembo.ai') ||
!['POST', 'PUT', 'DELETE'].includes(event.request.method) ||
event.request.url.endsWith('/login')
) {
return;
}
event.respondWith(processRequest(event.request));
});
Short dive in Queue code. I am create indicator in my code for running replayRequest
function and this help avoid dangerous behavior.
But question is steel open.
Why only sync event check that sync is in Progress? But not a replayRequest
function?
@jeffposnick Can I create PR with this check?
@jeffposnick can you share details for how to check with help of workbox that PWA app on android/IOS phone help to check app is running in background and keep calling notifications to fetch?