Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service worker stuck in busy state with NetworkFirst requests #2721

Closed
joshkel opened this issue Jan 11, 2021 · 5 comments · Fixed by #2744
Closed

Service worker stuck in busy state with NetworkFirst requests #2721

joshkel opened this issue Jan 11, 2021 · 5 comments · Fixed by #2744
Labels
Bug An issue with our existing, production codebase. Needs More Info Waiting on additional information from the community. workbox-strategies

Comments

@joshkel
Copy link
Contributor

joshkel commented Jan 11, 2021

Library Affected:

workbox-strategies 6.0.2

Browser & Platform:

Tested on Google Chrome 87.0.4280.141 for Windows

Issue or Feature Request Description:

My application is set up with the "offer a page reload" recipe and has a route registered with NetworkFirst. However, I noticed that the application wasn't responding when I clicked the upgrade prompt. Going under DevTools -> Application -> Service Workers and clicking "skipWaiting" next to the new service worker instance also seemed to have no effect. If I clicked "stop" next to the old service worker instance to forcibly terminate it, the application reloaded as expected. If I waited 5 minutes, the application reloaded as expected.

As best as I can tell, the symptoms are identical to #2692, except that I'm not using server-side events.

If I replace my NetworkFirst strategy with StaleWhileRevalidate, everything works.

Similar to #2692, calling waitUntil seems to fix this. Specifically, I found NetworkFirst's Promise.race call at

let response = await Promise.race(promises);

and inserted a waitUntil call there:

        let responsePromise = Promise.race(promises);
        handler.waitUntil(responsePromise);
        let response = await responsePromise;

I'm happy to open a PR if that would help, although, after reading the discussion at #2692, I wasn't sure if that's the correct fix.

@jeffposnick
Copy link
Contributor

Thanks for reporting this.

I would like to get to the bottom of this behavior—if we need to make changes to add in extra waitUntil() calls, then that's doable, but not understanding why means that we're potentially just papering over a larger issue.

Could you share the URL for your web app? You could DM @jeffposnick on Twitter if you can't share it publicly on GitHub.

@jeffposnick jeffposnick added Bug An issue with our existing, production codebase. Needs More Info Waiting on additional information from the community. workbox-strategies labels Jan 14, 2021
@jeffposnick
Copy link
Contributor

After debugging further, there is an active WebSocket connection established by the web app, so this is a duplicate of #2692

@joshkel
Copy link
Contributor Author

joshkel commented Jan 21, 2021

Thanks for investigating, @jeffposnick; I really appreciate it. I've been able to reproduce the issue without the WebSockect connections, so I don't think it's a duplicate. I sent you a DM with more details.

@jeffposnick
Copy link
Contributor

(This is a different issue, due to the NetworkFirst strategy waiting on a timeout promise that never resolves.)

philipwalton pushed a commit that referenced this issue Feb 17, 2021
* Fix NetworkFirst waitUntil

NetworkFirst's design uses two promises (one for the network request, and one for the timeout). If the network request succeeds, then the timeout promise's timer is canceled. However, it attempted to wait until both promises were done before marking the event as done; this meant that, if the network request succeeded, then it never resolved its handlerDone / awaitComplete promise.

This fixes #2721.

* Add a test to cover the timeout-not-exceeded case

* Explicitly verify that the promise resolved before timeout

* Properly handle network fallback

Improve typings for waitUntil; since the revised logic uses a callback, it can't rely on type inference as much.

* Code review feedback

Follow coding style; remove eventDoneWaiting calls, since that duplicates donePromise.
@jeffposnick
Copy link
Contributor

This is fixed in the v6.1.1 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug An issue with our existing, production codebase. Needs More Info Waiting on additional information from the community. workbox-strategies
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants