Skip to content

Commit b2b6495

Browse files
committed
refactor(shared-worker): reorganize SharedWorker code
Decouple and re-organize `SharedWorker` code for better maintainability. perf(shared-worker): improved subscription state refresh logic Additional query parameter (removed before sending) is added for requests triggered by user and state will be updated only for these requests. refactor(logger): avoid similar timestamp in sequential lines Log entry timestamp will be altered on millisecond if multiple log entries have similar timestamp (logged in fraction of nanoseconds).
1 parent 1fee158 commit b2b6495

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+9239
-4721
lines changed

dist/web/pubnub.js

Lines changed: 199 additions & 35 deletions
Large diffs are not rendered by default.

dist/web/pubnub.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/web/pubnub.worker.js

Lines changed: 3693 additions & 1838 deletions
Large diffs are not rendered by default.

dist/web/pubnub.worker.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/core/components/configuration.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ const makeConfiguration = (base, setupCryptoModule) => {
134134
getUseRandomIVs() {
135135
return base.useRandomIVs;
136136
},
137+
isSharedWorkerEnabled() {
138+
// @ts-expect-error: Access field from web-based SDK configuration.
139+
return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl'];
140+
},
137141
getKeepPresenceChannelsInPresenceRequests() {
138142
// @ts-expect-error: Access field from web-based SDK configuration.
139143
return base.sdkFamily === 'Web' && base['subscriptionWorkerUrl'];

lib/core/components/logger-manager.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ class LoggerManager {
1818
* @internal
1919
*/
2020
constructor(pubNubId, minLogLevel, loggers) {
21+
/**
22+
* Keeping track of previous entry timestamp.
23+
*
24+
* This information will be used to make sure that multiple sequential entries doesn't have same timestamp. Adjustment
25+
* on .001 will be done to make it possible to properly stort entries.
26+
*
27+
* @internal
28+
*/
29+
this.previousEntryTimestamp = 0;
2130
this.pubNubId = pubNubId;
2231
this.minLogLevel = minLogLevel;
2332
this.loggers = loggers;
@@ -100,8 +109,15 @@ class LoggerManager {
100109
// Check whether a log message should be handled at all or not.
101110
if (logLevel < this.minLogLevel || this.loggers.length === 0)
102111
return;
112+
const date = new Date();
113+
if (date.getTime() <= this.previousEntryTimestamp) {
114+
this.previousEntryTimestamp++;
115+
date.setTime(this.previousEntryTimestamp);
116+
}
117+
else
118+
this.previousEntryTimestamp = date.getTime();
103119
const level = logger_1.LogLevel[logLevel].toLowerCase();
104-
const message = Object.assign({ timestamp: new Date(), pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory }));
120+
const message = Object.assign({ timestamp: date, pubNubId: this.pubNubId, level: logLevel, minimumLevel: this.minLogLevel, location }, (typeof messageFactory === 'function' ? messageFactory() : { messageType: 'text', message: messageFactory }));
105121
this.loggers.forEach((logger) => logger[level](message));
106122
}
107123
}

lib/core/components/subscription-manager.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ class SubscriptionManager {
3838
this.subscribeCall = subscribeCall;
3939
this.heartbeatCall = heartbeatCall;
4040
this.leaveCall = leaveCall;
41+
/**
42+
* Whether user code in event handlers requested disconnection or not.
43+
*
44+
* Won't continue subscription loop if user requested disconnection/unsubscribe from all in response to received
45+
* event.
46+
*/
47+
this.disconnectedWhileHandledEvent = false;
4148
configuration.logger().trace('SubscriptionManager', 'Create manager.');
4249
this.reconnectionManager = new reconnection_manager_1.ReconnectionManager(time);
4350
this.dedupingManager = new deduping_manager_1.DedupingManager(this.configuration);
@@ -83,6 +90,9 @@ class SubscriptionManager {
8390
// endregion
8491
// region Subscription
8592
disconnect() {
93+
// Potentially called during received events handling.
94+
// Mark to prevent subscription loop continuation in subscribe response handler.
95+
this.disconnectedWhileHandledEvent = true;
8696
this.stopSubscribeLoop();
8797
this.stopHeartbeatTimer();
8898
this.reconnectionManager.stopPolling();
@@ -200,6 +210,7 @@ class SubscriptionManager {
200210
this.reconnect(true);
201211
}
202212
unsubscribeAll(isOffline = false) {
213+
this.disconnectedWhileHandledEvent = true;
203214
this.unsubscribe({
204215
channels: this.subscribedChannels,
205216
channelGroups: this.subscribedChannelGroups,
@@ -214,6 +225,7 @@ class SubscriptionManager {
214225
* @internal
215226
*/
216227
startSubscribeLoop(restartOnUnsubscribe = false) {
228+
this.disconnectedWhileHandledEvent = false;
217229
this.stopSubscribeLoop();
218230
const channelGroups = [...Object.keys(this.channelGroups)];
219231
const channels = [...Object.keys(this.channels)];
@@ -222,8 +234,8 @@ class SubscriptionManager {
222234
// There is no need to start subscription loop for an empty list of data sources.
223235
if (channels.length === 0 && channelGroups.length === 0)
224236
return;
225-
this.subscribeCall(Object.assign(Object.assign({ channels,
226-
channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), (status, result) => {
237+
this.subscribeCall(Object.assign(Object.assign(Object.assign({ channels,
238+
channelGroups, state: this.presenceState, heartbeat: this.configuration.getPresenceTimeout(), timetoken: this.currentTimetoken }, (this.region !== null ? { region: this.region } : {})), (this.configuration.filterExpression ? { filterExpression: this.configuration.filterExpression } : {})), { onDemand: !this.subscriptionStatusAnnounced || restartOnUnsubscribe }), (status, result) => {
227239
this.processSubscribeResponse(status, result);
228240
});
229241
if (!restartOnUnsubscribe && this.configuration.useSmartHeartbeat)
@@ -354,7 +366,10 @@ class SubscriptionManager {
354366
this.emitStatus(errorStatus);
355367
}
356368
this.region = result.cursor.region;
357-
this.startSubscribeLoop();
369+
if (!this.disconnectedWhileHandledEvent)
370+
this.startSubscribeLoop();
371+
else
372+
this.disconnectedWhileHandledEvent = false;
358373
}
359374
// endregion
360375
// region Presence

lib/core/constants/categories.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,12 @@ var StatusCategory;
100100
* PubNub client unexpectedly disconnected from the real-time updates streams.
101101
*/
102102
StatusCategory["PNDisconnectedUnexpectedlyCategory"] = "PNDisconnectedUnexpectedlyCategory";
103+
// --------------------------------------------------------
104+
// ------------------ Shared worker events ----------------
105+
// --------------------------------------------------------
106+
/**
107+
* SDK will announce when newer shared worker will be 'noticed'.
108+
*/
109+
StatusCategory["PNSharedWorkerUpdatedCategory"] = "PNSharedWorkerUpdatedCategory";
103110
})(StatusCategory || (StatusCategory = {}));
104111
exports.default = StatusCategory;

lib/core/endpoints/subscribe.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,10 @@ class SubscribeRequest extends BaseSubscribeRequest {
344344
return `/v2/subscribe/${subscribeKey}/${(0, utils_1.encodeNames)((_a = channels === null || channels === void 0 ? void 0 : channels.sort()) !== null && _a !== void 0 ? _a : [], ',')}/0`;
345345
}
346346
get queryParameters() {
347-
const { channelGroups, filterExpression, heartbeat, state, timetoken, region } = this.parameters;
347+
const { channelGroups, filterExpression, heartbeat, state, timetoken, region, onDemand } = this.parameters;
348348
const query = {};
349+
if (onDemand)
350+
query['on-demand'] = 1;
349351
if (channelGroups && channelGroups.length > 0)
350352
query['channel-group'] = channelGroups.sort().join(',');
351353
if (filterExpression && filterExpression.length > 0)

lib/core/endpoints/subscriptionUtils/handshake.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ class HandshakeSubscribeRequest extends subscribe_1.BaseSubscribeRequest {
2828
return `/v2/subscribe/${subscribeKey}/${(0, utils_1.encodeNames)(channels.sort(), ',')}/0`;
2929
}
3030
get queryParameters() {
31-
const { channelGroups, filterExpression, state } = this.parameters;
31+
const { channelGroups, filterExpression, state, onDemand } = this
32+
.parameters;
3233
const query = { ee: '' };
34+
if (onDemand)
35+
query['on-demand'] = 1;
3336
if (channelGroups && channelGroups.length > 0)
3437
query['channel-group'] = channelGroups.sort().join(',');
3538
if (filterExpression && filterExpression.length > 0)

0 commit comments

Comments
 (0)