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
Service worker locked in EXISTING_CLIENTS_ONLY state #31109
Comments
Finally I think even an update of the application, and thus a new Do you think a solution can be found, at least so the service worker can go out of the broken state on an |
I think a code diff that could work to restore the service worker nominal state after a degraded state could be: --- node_modules/@angular/service-worker/ngsw-worker.js
+++ node_modules/@angular/service-worker/ngsw-worker.js
@@ -2472,6 +2472,14 @@
// Future new clients will use this hash as the latest version.
this.latestHash = hash;
yield this.sync();
+ // A new version have been correctly fecthed and registered.
+ // It is ready to be assigned to previously disconnect clients
+ // and to new clients, thus let's go out of
+ // `EXISTING_CLIENTS_ONLY` mode now.
+ if (this.state == DriverReadyState.EXISTING_CLIENTS_ONLY) {
+ this.state = DriverReadyState.NORMAL;
+ this.stateMessage = '(nominal)';
+ }
yield this.notifyClientsAboutUpdate();
});
} @gkalpak Sorry to ping you, but maybe you have an opinion if it's a good proposal or not? |
Reading through your comments, everything sounds reasonable, @H--o-l. |
@H--o-l, I finally got around to looking into this. I think the current behavior is (sort of) intended. What you said above is correct, except that this only last for as long as the ServiceWorker instance is in The During debugging, you can verify that, by forcing the SW instance to be stopped:
So, once a ServiceWorker instance enters a degraded state (either |
Thanks for looking into this! Sorry for the long answer too, I wasn't here. It's an interesting fact that the Driver state is not persisted between service worker instances. That been said, I have some remarks around the design:
What do you think about it @gkalpak? |
Ooops, I meant Regarding your points:
Thx, again, for raising these points 👍 |
…there is a valid update Previously, when the ServiceWorker entered a degraded mode (`EXISTING_CLIENTS_ONLY` or `SAFE_MODE`) it would remain in that mode for the rest of the lifetime of ServiceWorker instance. Note that ServiceWorkers are stopped by the browser after a certain period of inactivity and a new instance is created as soon as the ServiceWorker needs to handle an event (such as a request from the page). Those new instances would start from the `NORMAL` mode. The reason for this behavior is to err on the side of caution: If we can't be sure why the ServiceWorker entered the degraded state, it is risky to try and recover on the same instance and might lead to unexpected behavior. However, it turns out that the `EXISTING_CLIENTS_ONLY` mode can only be a result of some error happening with the latest version (e.g. a hash mismatch in the manifest). Therefore, it is safe to recover from that mode once a new, valid update is successfully installed and start accepting new clients. This commit ensures that the mode is set nack to `NORMAL`, when (a) an update is successfully installed and (b) the mode was `EXISTING_CLIENTS_ONLY`. Fixes angular#31109
…there is a valid update Previously, when the ServiceWorker entered a degraded mode (`EXISTING_CLIENTS_ONLY` or `SAFE_MODE`) it would remain in that mode for the rest of the lifetime of ServiceWorker instance. Note that ServiceWorkers are stopped by the browser after a certain period of inactivity and a new instance is created as soon as the ServiceWorker needs to handle an event (such as a request from the page). Those new instances would start from the `NORMAL` mode. The reason for this behavior is to err on the side of caution: If we can't be sure why the ServiceWorker entered the degraded state, it is risky to try and recover on the same instance and might lead to unexpected behavior. However, it turns out that the `EXISTING_CLIENTS_ONLY` mode can only be a result of some error happening with the latest version (e.g. a hash mismatch in the manifest). Therefore, it is safe to recover from that mode once a new, valid update is successfully installed and start accepting new clients. This commit ensures that the mode is set nack to `NORMAL`, when (a) an update is successfully installed and (b) the mode was `EXISTING_CLIENTS_ONLY`. Fixes angular#31109
…there is a valid update Previously, when the ServiceWorker entered a degraded mode (`EXISTING_CLIENTS_ONLY` or `SAFE_MODE`) it would remain in that mode for the rest of the lifetime of ServiceWorker instance. Note that ServiceWorkers are stopped by the browser after a certain period of inactivity and a new instance is created as soon as the ServiceWorker needs to handle an event (such as a request from the page). Those new instances would start from the `NORMAL` mode. The reason for this behavior is to err on the side of caution: If we can't be sure why the ServiceWorker entered the degraded mode, it is risky to try recovering on the same instance and might lead to unexpected behavior. However, it turns out that the `EXISTING_CLIENTS_ONLY` mode can only be a result of some error happening with the latest version (e.g. a hash mismatch in the manifest). Therefore, it is safe to recover from that mode once a new, valid update is successfully installed and to start accepting new clients. This commit ensures that the mode is set back to `NORMAL`, when (a) an update is successfully installed and (b) the current mode is `EXISTING_CLIENTS_ONLY`. Besides making the behavior more predictable (instead of relying on the browser to decide when to terminate the current ServiceWorker instance and create a new one), this change can also improve the developer experience: When people notice the error during debugging and fix it by deploying a new version (either to production or locally), it is confusing that the ServiceWorker will fetch and install the update (as seen by the requests in the Network panel in DevTools) but not serve it to clients. With this change, the update will be served to new clients as soon as it is installed. Fixes angular#31109
OK, I thought about it some more and I believe it is reasonable to try to recover from |
Awesome! Of course feel free to adapt it, or made your how entirely! |
…there is a valid update (angular#31865) Previously, when the ServiceWorker entered a degraded mode (`EXISTING_CLIENTS_ONLY` or `SAFE_MODE`) it would remain in that mode for the rest of the lifetime of ServiceWorker instance. Note that ServiceWorkers are stopped by the browser after a certain period of inactivity and a new instance is created as soon as the ServiceWorker needs to handle an event (such as a request from the page). Those new instances would start from the `NORMAL` mode. The reason for this behavior is to err on the side of caution: If we can't be sure why the ServiceWorker entered the degraded mode, it is risky to try recovering on the same instance and might lead to unexpected behavior. However, it turns out that the `EXISTING_CLIENTS_ONLY` mode can only be a result of some error happening with the latest version (e.g. a hash mismatch in the manifest). Therefore, it is safe to recover from that mode once a new, valid update is successfully installed and to start accepting new clients. This commit ensures that the mode is set back to `NORMAL`, when (a) an update is successfully installed and (b) the current mode is `EXISTING_CLIENTS_ONLY`. Besides making the behavior more predictable (instead of relying on the browser to decide when to terminate the current ServiceWorker instance and create a new one), this change can also improve the developer experience: When people notice the error during debugging and fix it by deploying a new version (either to production or locally), it is confusing that the ServiceWorker will fetch and install the update (as seen by the requests in the Network panel in DevTools) but not serve it to clients. With this change, the update will be served to new clients as soon as it is installed. Fixes angular#31109 PR Close angular#31865
…there is a valid update (angular#31865) Previously, when the ServiceWorker entered a degraded mode (`EXISTING_CLIENTS_ONLY` or `SAFE_MODE`) it would remain in that mode for the rest of the lifetime of ServiceWorker instance. Note that ServiceWorkers are stopped by the browser after a certain period of inactivity and a new instance is created as soon as the ServiceWorker needs to handle an event (such as a request from the page). Those new instances would start from the `NORMAL` mode. The reason for this behavior is to err on the side of caution: If we can't be sure why the ServiceWorker entered the degraded mode, it is risky to try recovering on the same instance and might lead to unexpected behavior. However, it turns out that the `EXISTING_CLIENTS_ONLY` mode can only be a result of some error happening with the latest version (e.g. a hash mismatch in the manifest). Therefore, it is safe to recover from that mode once a new, valid update is successfully installed and to start accepting new clients. This commit ensures that the mode is set back to `NORMAL`, when (a) an update is successfully installed and (b) the current mode is `EXISTING_CLIENTS_ONLY`. Besides making the behavior more predictable (instead of relying on the browser to decide when to terminate the current ServiceWorker instance and create a new one), this change can also improve the developer experience: When people notice the error during debugging and fix it by deploying a new version (either to production or locally), it is confusing that the ServiceWorker will fetch and install the update (as seen by the requests in the Network panel in DevTools) but not serve it to clients. With this change, the update will be served to new clients as soon as it is installed. Fixes angular#31109 PR Close angular#31865
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
🐞 bug report
Affected Package
The issue is caused by package @angular/pwa
Is this a regression?
Not a regression I think.
Description
If a network failure happens, the service worker will enter the
EXISTING_CLIENTS_ONLY
state.If a connected client reloads (F5), the service worker will stay in that state
forever and serve nothing to the client, nor to other clients or reloading clients.
In my opinion, it would be better if the service worker kept serving the old
cached version, while waiting for the network to recover and the update to occur successfully.
Otherwise, offline mode is broken.
🔬 Minimal Reproduction
To enter
EXISTING_CLIENTS_ONLY
state:Create an Angular app:
Open
http://localhost:8080
in Chrome and wait for the pageKill the server
Change something in
src/app/app.component.html
Rebuild and serve:
Go back in Chrome, it
slow 3g network
in dev tool, hit F5, and wait forthe service worker to start downloading
index.html
,main.js
or any file ofthe update.
When that happen, check chrome devtool
Offline
checkbox.The service worker is now in
EXISTING_CLIENTS_ONLY
.From now, to create the issue, just hit F5.
The application will be broken offline, even after network reconnection,
tab close/re-open, etc.
For me, beside unregistering the service worker manually, only a new update of
the application can fix the state.
🌍 Your Environment
Angular Version:
Anything else relevant?
Only tested on Chrome.
The text was updated successfully, but these errors were encountered: