Design pattern for keeping service worker running

230 views
Skip to first unread message

Juraj M.

unread,
Aug 11, 2023, 3:58:38 AM8/11/23
to Chromium Extensions
I have a fetch call that can take more than 30 seconds to complete and I want to prevent service worker to stop.
I've read somewhere here that calling some API will postpone it, but which one to choose?
Is there some "best practice" for doing that?

Here is my super simple use-case:
for (const work of cloudScheduled) {
   // WARNING: in some cases the reload can take more than one minute!
   await cloudReload(work);
}

I imagine someone already implemented some "withoutKilling" helper function that takes function as parameter and it will start some "light" infinite loop, then awaits the function call and then stops the infinite loop :).
Message has been deleted
Message has been deleted

M. Ángel González

unread,
Aug 11, 2023, 7:10:02 AM8/11/23
to Chromium Extensions, Juraj M.


There are two APIs you can use to delay the service worker: setTimeout() and setInterval(). setTimeout() delays the service worker for a specified period of time, while setInterval() delays the service worker at regular intervals.

In your case, you can use setTimeout() to delay the service worker for 30 seconds. The following code shows how to do this:

for (const work of cloudScheduled) { // WARNING: In some cases, the reload may take more than a minute! setTimeout(() => { await cloudReload(work); }, 30000); }

This is a best practice for delaying the service worker:

  • Use the API that best suits your needs. If you need to delay the service worker for a specified period of time, use setTimeout(). If you need to delay the service worker at regular intervals, use setInterval().
  • Make sure the delay period or interval is long enough to allow the fetch call to complete.
  • Avoid delaying the service worker for too long, as this can affect the performance of your application.

Oliver Dunk

unread,
Aug 11, 2023, 7:20:58 AM8/11/23
to M. Ángel González, Chromium Extensions, Juraj M.
M - thanks for the suggestions! Those are good for delaying work by a fixed time but won't do anything to keep the service worker alive. In fact, it may be terminated before running the code in the setTimeout.

A call to any extension API (or to be precise, most APIs - there are a few exceptions like runtime.getURL) will extend the lifetime. Of course this is a bit of a hack, so I would suggest trying to do something at least slightly useful. A good one I've seen in the past is having a setInterval that runs every 5 seconds or so and sets a "last-heartbeat" timestamp using the chrome.storage API. It's a fairly lightweight operation and you can explain in some comments why it exists and that it should only be used when absolutely needed.

Of course we'd like to solve this properly - I think fetch is still a pretty good candidate for a built-in keep alive, which has been brought up in https://bugs.chromium.org/p/chromium/issues/detail?id=1418780, but we haven't quite got to that yet.
Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB


--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/0357d3dc-567a-46a9-bd04-97fdfffae8e6n%40chromium.org.

Juraj M.

unread,
Aug 11, 2023, 7:52:26 AM8/11/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Juraj M., M. Ángel González
Thank you Oliver.
Although I'm a fan of the workaround you've proposed. Performing IO operation every 5 seconds sounds like an overkill. Maybe every 20 seconds (since 30 is the hard limit, right?). 
And maybe using `storage.session` to avoid IO? But still, knowing how many even storage.onchanged handlers will fire all over my codebase just to keep my worker alive... (it's probably just my OCD talking now :D)

Maybe there is a better option? Like "chrome.runtime.getManifest()". Or maybe something that doesn't do anything, like `await chrome.tabs.getCurrent()` which will always return undefined.
Is there a list of API that are excluded like the getURL you've mentioned? Or how can I tell?

Juraj M.

unread,
Aug 11, 2023, 8:12:09 AM8/11/23
to Chromium Extensions, Juraj M., Oliver Dunk, Chromium Extensions, M. Ángel González
I had something like this in mind, would it work to keep worker alive?

// executes long-running async work without letting the service worker to die
export async function withoutKillingWorker<T>(asyncWork: () => Promise<T>): Promise<T> {
  const id = self.setInterval(() => browser.tabs.getCurrent(), 2e4);
  return await asyncWork().finally(() => self.clearInterval(id));
}

Oliver Dunk

unread,
Aug 11, 2023, 9:55:38 AM8/11/23
to Juraj M., Chromium Extensions, M. Ángel González
Hey Juraj,

That looks like it would work to me - of course, the call to tabs.getCurrent() is quite redundant (mostly saying this for anyone else who finds the thread) but it's nice that it will only happen until the work is complete. Given the 30 second timeout, it should hopefully be fairly trivial to test and confirm :)

There isn't a way to easily tell which APIs this applies to, which is part of the reason we have https://crbug.com/1446810 open to look at doing this more consistently. There is a list of exceptions in that bug which should be fairly complete, and runtime.getManifest is one of them. In that case specifically I'm fairly sure it doesn't extend the lifetime because that happens in the renderer rather than needing to go to another process - here specifically.
Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB

Juraj M.

unread,
Aug 11, 2023, 10:09:03 AM8/11/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, M. Ángel González, Juraj M.
Thank you Oliver for the additional info, I've just tested it and it works well (the worker will stay alive as long as the job runs).
Have a nice weekend! :)

Oliver Dunk

unread,
Aug 11, 2023, 10:10:14 AM8/11/23
to Juraj M., Chromium Extensions, M. Ángel González
Of course - you too!
Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB

Reply all
Reply to author
Forward
0 new messages