How to stop a background script from going idle in MV3?

I am in Manifest v3, and have a background script that is polling an API every 30 seconds, using setTimeout to continuously make those calls.

My problem is that after 45 - 90 seconds the background script always stops. If I have the extension debugger on, the script stays active and says:

Background event page was not terminated on idle because a DevTools toolbox is attached to the extension.

Is there any way to stop this script from being terminated?

After digging around some I found this StackOverflow thread, which lists a number of workarounds.

The solution that I used was setting alarms (1 minute period), which seem to wake the script up when they go off, as well as extend the idle time. One alarm going off every minute wasn’t enough to keep the script alive. I set three alarms, staggered so that each goes off every 20 seconds, and that seems to work.

browser.alarms.create("keep-loaded-alarm-0", {
  periodInMinutes: 1
});
setTimeout(() => browser.alarms.create("keep-loaded-alarm-1", {
  periodInMinutes: 1
}), "20000");
setTimeout(() => browser.alarms.create("keep-loaded-alarm-2", {
  periodInMinutes: 1
}), "40000");

browser.alarms.onAlarm.addListener(() => {
  console.log("keeping extension alive - log for debug");
});

The only caveat is that the script shuts off initially, and then comes back on after the first alarm goes off for the first time (alarms don’t go off for a minute, so the script is idle 1 minute before anything extends it). For my use case, this isn’t a massive issue.

Altenatively, in Firefox you can still use MV2 and persistent background script.
Apart from the few changes in the manifest file, there are almost no differences when “downgrading” MV3 to MV2.

1 Like

@717eanderson, why are you trying to prevent the extension’s background from going idle? Generally speaking this is an anti-pattern and should be avoided. If you can share more about your use case we may be able to offer other solutions.

1 Like

I’m polling an API every 30 seconds. If the response changes, I send the user a notification. Relevant code is here. I want the script to run constantly to essentially simulate push notifications.

The thing is, I could let the script go idle, but then I need to wake it up somehow when it’s time to poll the API (I suppose I could use alarms to do this, but that’s basically what I’m doing already).

The other issue is that if I let the script go idle between API fetches, it adds complexity to the code. My “cache” of the last response would have to be stored in browser storage, since local variables in the script reset. If I did this I would also need some way to tell if the user just opened Firefox (so they don’t get notifications from the previous day, for example). This would probably require storing a timestamp in browser storage.

Other ways of achieving this were discussed here as well: Impossible to upgrade to manifest v3 for extensions that require constant/persistent listeners

Hm… while using push notifications would be preferable from a client resource consumption point of view, that approach would also introduce a server component and therefore even more complexity and cost.

If it isn’t already, persisting and restoring application state across background sessions is becoming standard practice. That said, I’m not aware of any good libraries or guides I could direct you to that show this in practice. Welp, I guess I’ll need to put on together.

Last thought: is there any particular reason you currently poll every 30 seconds? For comparison, a number of desktop email clients auto-poll every 5-15 minutes.

1 Like

I don’t have a particularly good reason to poll every 30 seconds. I made the extension poll pretty often because for its purpose it’s amusing to receive immediate notifications when the API updates.

I could probably increase the amount of time between API calls to a couple of minutes, in which case using an alarm to wake up the script would make more sense.

1 Like