If a website is experiencing an outage, but LibResilient is deployed on it and is working correctly for the visitors whose browsers were able to install and activate it before the disruption started, it is possible to update LibResilient configuration using any alternative transport plugins available.
It is not, however, possible to load plugins that have not been previously loaded based on the previous
config.json, as this would require a call to
importScripts() and thus: a direct HTTPS request to the original domain.
The Service Worker API allows for updating the service worker script itself and any imported scripts (via
importScripts()) only via a direct HTTPS request to the original domain.
LibResilient expects configuration in a
config.json file, not in a script, so that it can be retrieved and used without a call to
importScripts(). This allows updating the configuration during disruptions. The
importScripts() limitation still affects plugin scripts, however: it is not possible to load new plugin scripts while the original website is experiencing disruption or outage.
LibResilient’s Service Worker needs the
config.json configuration script every time it is installed or re-started.
Service Worker installation happens upon loading the website for the first time. Re-start of the Service Worker can happen at any time — it’s up to the browser to decide when to stop a Service Worker. This usually happens after all relevant tabs are closed, or some time after the last request even if the tabs are open. A previously installed Service Worker is started whenever there is an event for it to handle; in case of LibResilient that will almost always be a
When a Service Worker is stopped, all context (variables, state, etc) is lost. Only the Service Worker script (in our case,
service-worker.js) and any scripts imported in it using
importScripts() remain cached, along with other contents of the cache (and other WebAPIs that are not relevant here).
For LibResilient this means that when an already installed, but stopped, Service Worker gets started again, all plugin initialization needs to happen from scratch. And for that we have to have the
When installing or handling any kind of event, the LibResilient Service Worker script first tries to retrieve the
config.json file. The first place to look is the cache. If there is a valid
config.json available there, it is used to configure and initialize the plugins.
If there is no
config.json available in cache, the only way to get it at this stage (as plugins are not configured yet) is a regular HTTPS
fetch() request to the original domain. If that works, the retrieved
config.json is cached for future use (that is, next time when the Service Worker has been stopped and is being started again) and used to configure and initialize the plugins.
If there is no
config.json available in cache, and the
fetch() request does not produce a valid
config.json either, LibResilient falls back to the default config (that is, a pretty trivial set-up using
cache). At this stage LibResilient Service Worker can start handling requests generated by the open tabs.
After configuring and initializing the plugins, LibResilient checks if the cached
config.json (if available) is older than 24h, based on the
Date: header in the response. If it is, it is considered stale, and a new background request for
config.json is started, this time using the now available already-initialized plugin infrastructure. At this stage, if alternative transport plugins are configured, updated
config.json can be retrieved even if the original website is experiencing disruptions or downtime.
However, due to the
importScripts() limitation, if a
config.json file is retrieved using alternative transport plugins (not via the
fetch plugin), it is expected not to introduce plugins that have not been used before — only to change the configuration of already-loaded plugins. If a plugin that has not been loaded beforehand is present, that
config.json file is ignored and discarded.
The reasoning behind this is that at this stage we do have a working configuration, as we were able to retrieve
config.json even though the original website is not available. So it’s better to keep using that proven configuration, rather than risk having to call
importScripts() for a new plugin, which might fail due to original website apparently not being available.