docs: UPDATING_DURING_DISRUPTION.md (ref. #30)

merge-requests/12/merge
Michał 'rysiek' Woźniak 2022-02-08 20:54:57 +00:00
rodzic 50fad1daa0
commit 27f3cbf908
1 zmienionych plików z 33 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,33 @@
# Updating the configuration during disruption
The [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) allows for updating the service worker script itself and any imported scripts (via [`importScripts()`](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts)) only via a direct HTTPS request to the original domain.
For this reason, LibResilient expects configuration in a `config.json` file, not in a script loaded via `importScripts()`. This allows updating the configuration during disruptions. The `importScripts()` limitation still affects plugin scripts, however.
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 loaded based on the previous `config.json`, as this would require using `importScripts()` and thus: a direct HTTPS request to the original domain.
## LibResilient's Service Worker lifecycle
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 [`fetch` event](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent).
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](https://developer.mozilla.org/en-US/docs/Web/API/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 `config.json` available.
## Initial loading of the config file
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 `fetch` and `cache`). At this stage LibResilient Service Worker can start handling requests generated by the open tabs.
## Updating the config file
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.