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

Detecting service worker termination #1550

Closed
Ale763 opened this issue Oct 28, 2020 · 4 comments
Closed

Detecting service worker termination #1550

Ale763 opened this issue Oct 28, 2020 · 4 comments

Comments

@Ale763
Copy link

Ale763 commented Oct 28, 2020

Is there a way to detect when a service worker is about to be suspended/terminated when it's not needed?
Browsers aggressively terminate service workers, in order to save resources.

But what if I wanted to do some computations based on the requests done by the web pages?
I'd like to perform some bookkeeping and save this to IndexedDB. However, at the moment I'm forced to write my computations for every single request to the database. I'd like to batch these writes, in one big write just before the service worker is about to be suspended.

I envision it could be interesting to perform some minor work, such as saving these kinds of computations to the database, by introducing a beforeTerminate event. This could be a very limited event in which only small amounts of work would be allowed and after which the service worker would be immediately terminated.

Does anyone have any thoughts on this or is there another way to accomplish this?

@asutherland
Copy link

If your ServiceWorker is doing additional processing resulting from a FetchEvent, then you will want to make sure that you are using ExtendableEvent.waitUntil to indicate that processing is ongoing. This is best used with the new (not present in all browsers yet) FetchEvent.handled promise which can let you defer your processing until the response has been sufficiently processed. See #1397 for more details/context on that.

If your processing is resource intensive or has a duration that exceeds the normal waitUntil grace periods, then it might be advisable to perform that computation in a dedicated or SharedWorker so you don't impact the responsiveness of the ServiceWorker or trigger browser interventions that mark your ServiceWorker as broken.

@Ale763
Copy link
Author

Ale763 commented Nov 2, 2020

Thank you for your fast reply. I will look into this and verify if I can find a way to use this as a workaround.

However, I'm not really sure this is the best way to handle the situation I have in mind, but I could be wrong.
Say I load some data into the service worker in order to do some complex decision making about routing and managing the cache. If I understand it correctly, in order to not lose the progress made, I have to write the entire state into the database after the response has been returned to the main thread. This still seems wasteful to me, as a page load will require the service worker to process multiple resources, they will have to be written for every request for that page. I don't know when the FetchEvent.handled will be executed, but if that happens in between these requests, it will slow down the loading of the page.

With that in mind, a beforeTerminate event could be helpful to perform some one-time work to consolidate the state that's in memory, instead of having to do this needlessly after every request.

Does that makes sense or do you still think your solution is the best way to go?

@asutherland
Copy link

beforeTerminate runs counter to the existing ServiceWorker design of having the worker clearly delineate what ExtendableEvents are still processing through use of waitUntil and is likely a non-starter. For example, the plan is to break all web locks if a ServiceWorker does not have any active ExtendableEvents.

The SW can call both FetchEvent.respondWith and FetchEvent.waitUntil. The respondWith can resolve in a very timely fashion like 100msec and you can spend on the order of seconds or tens of seconds continuing to perform amortized cache cleanup before resolving the promise passed to waitUntil. handled will be resolved shortly after your respondWith promise resolves; its goal is to enable a ServiceWorker to avoid interfering with any on-thread processing that happens as part of consuming the Response that was received by respondWith.

@asutherland
Copy link

Also, it's fine to coordinate the amortized cleanup work using global variables set in the ServiceWorker (protected by an active waitUntil). That is, while it's appropriate to regularly checkpoint state to storage, there's no need to be paranoid about avoiding the use of globals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants