Skip to content

Commit

Permalink
refactor(service-worker): unresponsive clients clean up
Browse files Browse the repository at this point in the history
Clean up internal Subscription Service Worker state from information about PubNub client which
is not reachable through Service Worker Client (client with linked ID can't be fetched).
  • Loading branch information
parfeon committed Apr 22, 2024
1 parent 6bc21fa commit 096315f
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"clearedSuffix": false
}
],
"src/core/components/config.js": [
"src/core/components/configuration.ts": [
{
"pattern": "^\\s{2,}return '(v?(\\.?\\d+){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?)';$",
"clearedPrefix": true,
Expand Down
16 changes: 7 additions & 9 deletions dist/web/pubnub.js
Original file line number Diff line number Diff line change
Expand Up @@ -3672,12 +3672,13 @@
var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports);

var uuidGenerator = {
createUUID() {
if (uuidGenerator$1.uuid) {
return uuidGenerator$1.uuid();
}
return uuidGenerator$1();
},
createUUID() {
if (uuidGenerator$1.uuid) {
return uuidGenerator$1.uuid();
}
// @ts-expect-error Depending on module type it may be callable.
return uuidGenerator$1();
},
};

/**
Expand Down Expand Up @@ -6450,7 +6451,6 @@
channels,
groups,
}));
// TODO: Find out actual `status` type.
/* eslint-disable @typescript-eslint/no-explicit-any */
const emitStatus$1 = createEffect('EMIT_STATUS', (status) => status);
const wait = createManagedEffect('WAIT', () => ({}));
Expand Down Expand Up @@ -6685,7 +6685,6 @@
return {
delay: configuration.delay,
maximumRetry: configuration.maximumRetry,
// TODO: Find out actual `error` type.
/* eslint-disable @typescript-eslint/no-explicit-any */
shouldRetry(error, attempt) {
var _a;
Expand All @@ -6699,7 +6698,6 @@
const delay = (_a = reason.retryAfter) !== null && _a !== void 0 ? _a : this.delay;
return (delay + Math.random()) * 1000;
},
// TODO: Find out actual `error` type.
/* eslint-disable @typescript-eslint/no-explicit-any */
getGiveupReason(error, attempt) {
var _a;
Expand Down
74 changes: 61 additions & 13 deletions dist/web/pubnub.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,13 @@
var uuidGenerator$1 = /*@__PURE__*/getDefaultExportFromCjs(uuidExports);

var uuidGenerator = {
createUUID() {
if (uuidGenerator$1.uuid) {
return uuidGenerator$1.uuid();
}
return uuidGenerator$1();
},
createUUID() {
if (uuidGenerator$1.uuid) {
return uuidGenerator$1.uuid();
}
// @ts-expect-error Depending on module type it may be callable.
return uuidGenerator$1();
},
};

/// <reference lib="webworker" />
Expand Down Expand Up @@ -208,6 +209,11 @@
markRequestCompleted(clients, requestOrId.identifier);
});
};
/**
* Handle client request to leave request.
*
* @param event - Leave event details.
*/
const handleSendLeaveRequestEvent = (event) => {
const data = event.data;
const request = leaveTransportRequestFromEvent(data);
Expand All @@ -222,7 +228,10 @@
result.url = `${data.request.origin}${data.request.path}`;
result.clientIdentifier = data.clientIdentifier;
result.identifier = data.request.identifier;
publishClientEvent(event.source.id, result);
publishClientEvent(event.source.id, result).then((sent) => {
if (sent)
invalidateClient(client.subscriptionKey, client.clientIdentifier, client.userId);
});
return;
}
sendRequest(request, () => [client], (clients, response) => {
Expand Down Expand Up @@ -504,10 +513,11 @@
* @param event - Service worker event object.
*/
const publishClientEvent = (identifier, event) => {
self.clients.get(identifier).then((client) => {
return self.clients.get(identifier).then((client) => {
if (!client)
return;
return false;
client.postMessage(event);
return true;
});
};
/**
Expand Down Expand Up @@ -559,7 +569,10 @@
const { request: clientRequest } = client.subscription;
const decidedRequest = clientRequest !== null && clientRequest !== void 0 ? clientRequest : request;
if (client.logVerbosity && serviceWorkerClientId && decidedRequest) {
publishClientEvent(serviceWorkerClientId, Object.assign(Object.assign({}, event), { clientIdentifier: client.clientIdentifier, url: `${decidedRequest.origin}${decidedRequest.path}`, query: decidedRequest.queryParameters }));
publishClientEvent(serviceWorkerClientId, Object.assign(Object.assign({}, event), { clientIdentifier: client.clientIdentifier, url: `${decidedRequest.origin}${decidedRequest.path}`, query: decidedRequest.queryParameters })).then((sent) => {
if (sent)
invalidateClient(client.subscriptionKey, client.clientIdentifier, client.userId);
});
}
});
};
Expand Down Expand Up @@ -590,7 +603,10 @@
const { request: clientRequest } = client.subscription;
const decidedRequest = clientRequest !== null && clientRequest !== void 0 ? clientRequest : request;
if (serviceWorkerClientId && decidedRequest) {
publishClientEvent(serviceWorkerClientId, Object.assign(Object.assign({}, result), { clientIdentifier: client.clientIdentifier, identifier: decidedRequest.identifier, url: `${decidedRequest.origin}${decidedRequest.path}` }));
publishClientEvent(serviceWorkerClientId, Object.assign(Object.assign({}, result), { clientIdentifier: client.clientIdentifier, identifier: decidedRequest.identifier, url: `${decidedRequest.origin}${decidedRequest.path}` })).then((sent) => {
if (sent)
invalidateClient(client.subscriptionKey, client.clientIdentifier, client.userId);
});
}
});
};
Expand Down Expand Up @@ -696,7 +712,6 @@
userId: query.uuid,
authKey: ((_c = query.auth) !== null && _c !== void 0 ? _c : ''),
logVerbosity: information.logVerbosity,
lastAvailabilityCheck: new Date().getTime(),
subscription: {
path: !isPresenceLeave ? information.request.path : '',
channelGroupQuery: !isPresenceLeave ? channelGroupQuery : '',
Expand Down Expand Up @@ -728,7 +743,6 @@
client.subscription.filterExpression = ((_o = query['filter-expr']) !== null && _o !== void 0 ? _o : '');
client.subscription.previousTimetoken = client.subscription.timetoken;
client.subscription.timetoken = ((_p = query.tt) !== null && _p !== void 0 ? _p : '0');
client.lastAvailabilityCheck = new Date().getTime();
client.subscription.request = information.request;
client.authKey = ((_q = query.auth) !== null && _q !== void 0 ? _q : '');
client.userId = query.uuid;
Expand Down Expand Up @@ -759,6 +773,40 @@
}
}
};
/**
* Clean up resources used by registered PubNub client instance.
*
* @param subscriptionKey - Subscription key which has been used by the
* invalidated instance.
* @param clientId - Unique PubNub client identifier.
* @param userId - Unique identifier of the user used by PubNub client instance.
*/
const invalidateClient = (subscriptionKey, clientId, userId) => {
delete pubNubClients[clientId];
let clients = pubNubClientsBySubscriptionKey[subscriptionKey];
if (clients) {
// Clean up linkage between client and subscription key.
clients = clients.filter((client) => client.clientIdentifier !== clientId);
if (clients.length > 0)
pubNubClientsBySubscriptionKey[subscriptionKey] = clients;
else
delete pubNubClientsBySubscriptionKey[subscriptionKey];
// Clean up presence state information if not in use anymore.
if (clients.length === 0)
delete presenceState[subscriptionKey];
// Clean up service workers client linkage to PubNub clients.
if (clients.length > 0) {
const workerClients = serviceWorkerClients[subscriptionKey];
if (workerClients) {
delete workerClients[clientId];
if (Object.keys(workerClients).length === 0)
delete serviceWorkerClients[subscriptionKey];
}
}
else
delete serviceWorkerClients[subscriptionKey];
}
};
/**
* Validate received event payload.
*/
Expand Down
Loading

0 comments on commit 096315f

Please sign in to comment.