fix(service-worker): keep serving clients on older versions if latest is invalidated (#31865)

Previously, when the latest version was invalidated (e.g. due to a hash
mismatch), the SW entered a degraded `EXISTING_CLIENTS_ONLY` mode and
removed _all_ clients from its client-version map (essentially stopping
to serve any clients). Based on the code and surrounding comments, the
intention seems to have been to only remove clients that were on the
invalidated version, but keep other clients on older versions.

This commit fixes it by only unassigning clients what were on the latest
version and keep clients assigned to older versions.

PR Close #31865
This commit is contained in:
George Kalpakas
2019-07-26 20:15:56 +03:00
committed by Miško Hevery
parent 20dc5e83ee
commit bda2b4ebb6
2 changed files with 89 additions and 13 deletions

View File

@ -742,11 +742,16 @@ export class Driver implements Debuggable, UpdateSource {
// This particular AppVersion is broken. First, find the manifest hash.
const broken =
Array.from(this.versions.entries()).find(([hash, version]) => version === appVersion);
if (broken === undefined) {
// This version is no longer in use anyway, so nobody cares.
return;
}
const brokenHash = broken[0];
const affectedClients = Array.from(this.clientVersionMap.entries())
.filter(([clientId, hash]) => hash === brokenHash)
.map(([clientId]) => clientId);
// TODO: notify affected apps.
@ -759,17 +764,12 @@ export class Driver implements Debuggable, UpdateSource {
this.state = DriverReadyState.EXISTING_CLIENTS_ONLY;
this.stateMessage = `Degraded due to: ${errorToString(err)}`;
// Cancel the binding for these clients.
Array.from(this.clientVersionMap.keys())
.forEach(clientId => this.clientVersionMap.delete(clientId));
// Cancel the binding for the affected clients.
affectedClients.forEach(clientId => this.clientVersionMap.delete(clientId));
} else {
// The current version is viable, but this older version isn't. The only
// The latest version is viable, but this older version isn't. The only
// possible remedy is to stop serving the older version and go to the network.
// Figure out which clients are affected and put them on the latest.
const affectedClients =
Array.from(this.clientVersionMap.keys())
.filter(clientId => this.clientVersionMap.get(clientId) ! === brokenHash);
// Push the affected clients onto the latest version.
// Put the affected clients on the latest version.
affectedClients.forEach(clientId => this.clientVersionMap.set(clientId, this.latestHash !));
}