@webex/internal-plugin-mercury 3.10.0-multi-llms.1 → 3.10.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.js.map +1 -1
- package/dist/errors.js +18 -24
- package/dist/errors.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mercury.js +208 -390
- package/dist/mercury.js.map +1 -1
- package/dist/socket/index.js.map +1 -1
- package/dist/socket/socket-base.js +11 -30
- package/dist/socket/socket-base.js.map +1 -1
- package/dist/socket/socket.js.map +1 -1
- package/dist/socket/socket.shim.js.map +1 -1
- package/package.json +17 -17
- package/src/mercury.js +184 -374
- package/src/socket/socket-base.js +0 -13
- package/test/unit/spec/mercury-events.js +2 -20
- package/test/unit/spec/mercury.js +32 -53
package/src/mercury.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import url from 'url';
|
|
7
7
|
|
|
8
8
|
import {WebexPlugin} from '@webex/webex-core';
|
|
9
|
-
import {deprecated} from '@webex/common';
|
|
9
|
+
import {deprecated, oneFlight} from '@webex/common';
|
|
10
10
|
import {camelCase, get, set} from 'lodash';
|
|
11
11
|
import backoff from 'backoff';
|
|
12
12
|
|
|
@@ -25,7 +25,6 @@ const normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'p
|
|
|
25
25
|
const Mercury = WebexPlugin.extend({
|
|
26
26
|
namespace: 'Mercury',
|
|
27
27
|
lastError: undefined,
|
|
28
|
-
defaultSessionId: 'mercury-default-session',
|
|
29
28
|
|
|
30
29
|
session: {
|
|
31
30
|
connected: {
|
|
@@ -40,18 +39,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
40
39
|
default: false,
|
|
41
40
|
type: 'boolean',
|
|
42
41
|
},
|
|
43
|
-
|
|
44
|
-
default: () => new Map(),
|
|
45
|
-
type: 'object',
|
|
46
|
-
},
|
|
47
|
-
backoffCalls: {
|
|
48
|
-
default: () => new Map(),
|
|
49
|
-
type: 'object',
|
|
50
|
-
},
|
|
51
|
-
_shutdownSwitchoverBackoffCalls: {
|
|
52
|
-
default: () => new Map(),
|
|
53
|
-
type: 'object',
|
|
54
|
-
},
|
|
42
|
+
socket: 'object',
|
|
55
43
|
localClusterServiceUrls: 'object',
|
|
56
44
|
mercuryTimeOffset: {
|
|
57
45
|
default: undefined,
|
|
@@ -111,60 +99,50 @@ const Mercury = WebexPlugin.extend({
|
|
|
111
99
|
/**
|
|
112
100
|
* Attach event listeners to a socket.
|
|
113
101
|
* @param {Socket} socket - The socket to attach listeners to
|
|
114
|
-
* @param {sessionId} sessionId - The socket related session ID
|
|
115
102
|
* @returns {void}
|
|
116
103
|
*/
|
|
117
|
-
_attachSocketEventListeners(socket
|
|
118
|
-
socket.on('close', (event) => this._onclose(
|
|
119
|
-
socket.on('message', (...args) => this._onmessage(
|
|
120
|
-
socket.on('pong', (...args) => this._setTimeOffset(
|
|
121
|
-
socket.on('sequence-mismatch', (...args) =>
|
|
122
|
-
|
|
123
|
-
);
|
|
124
|
-
socket.on('ping-pong-latency', (...args) =>
|
|
125
|
-
this._emit(sessionId, 'ping-pong-latency', ...args)
|
|
126
|
-
);
|
|
104
|
+
_attachSocketEventListeners(socket) {
|
|
105
|
+
socket.on('close', (event) => this._onclose(event, socket));
|
|
106
|
+
socket.on('message', (...args) => this._onmessage(...args));
|
|
107
|
+
socket.on('pong', (...args) => this._setTimeOffset(...args));
|
|
108
|
+
socket.on('sequence-mismatch', (...args) => this._emit('sequence-mismatch', ...args));
|
|
109
|
+
socket.on('ping-pong-latency', (...args) => this._emit('ping-pong-latency', ...args));
|
|
127
110
|
},
|
|
128
111
|
|
|
129
112
|
/**
|
|
130
113
|
* Handle imminent shutdown by establishing a new connection while keeping
|
|
131
114
|
* the current one alive (make-before-break).
|
|
132
115
|
* Idempotent: will no-op if already in progress.
|
|
133
|
-
* @param {string} sessionId - The session ID for which the shutdown is imminent
|
|
134
116
|
* @returns {void}
|
|
135
117
|
*/
|
|
136
|
-
_handleImminentShutdown(
|
|
137
|
-
const oldSocket = this.sockets.get(sessionId);
|
|
138
|
-
|
|
118
|
+
_handleImminentShutdown() {
|
|
139
119
|
try {
|
|
140
|
-
if (this.
|
|
141
|
-
this.logger.info(
|
|
142
|
-
`${this.namespace}: [shutdown] switchover already in progress for ${sessionId}`
|
|
143
|
-
);
|
|
120
|
+
if (this._shutdownSwitchoverInProgress) {
|
|
121
|
+
this.logger.info(`${this.namespace}: [shutdown] switchover already in progress`);
|
|
144
122
|
|
|
145
123
|
return;
|
|
146
124
|
}
|
|
125
|
+
this._shutdownSwitchoverInProgress = true;
|
|
147
126
|
this._shutdownSwitchoverId = `${Date.now()}`;
|
|
148
127
|
this.logger.info(
|
|
149
|
-
`${this.namespace}: [shutdown] switchover start, id=${this._shutdownSwitchoverId}
|
|
128
|
+
`${this.namespace}: [shutdown] switchover start, id=${this._shutdownSwitchoverId}`
|
|
150
129
|
);
|
|
151
130
|
|
|
152
|
-
this._connectWithBackoff(undefined,
|
|
131
|
+
this._connectWithBackoff(undefined, {
|
|
153
132
|
isShutdownSwitchover: true,
|
|
154
133
|
attemptOptions: {
|
|
155
134
|
isShutdownSwitchover: true,
|
|
156
135
|
onSuccess: (newSocket, webSocketUrl) => {
|
|
157
136
|
this.logger.info(
|
|
158
|
-
`${this.namespace}: [shutdown] switchover connected, url: ${webSocketUrl}
|
|
137
|
+
`${this.namespace}: [shutdown] switchover connected, url: ${webSocketUrl}`
|
|
159
138
|
);
|
|
160
139
|
|
|
140
|
+
const oldSocket = this.socket;
|
|
161
141
|
// Atomically switch active socket reference
|
|
162
|
-
this.socket =
|
|
163
|
-
this.connected =
|
|
142
|
+
this.socket = newSocket;
|
|
143
|
+
this.connected = true; // remain connected throughout
|
|
164
144
|
|
|
165
|
-
this._emit(
|
|
166
|
-
url: webSocketUrl,
|
|
167
|
-
});
|
|
145
|
+
this._emit('event:mercury_shutdown_switchover_complete', {url: webSocketUrl});
|
|
168
146
|
|
|
169
147
|
if (oldSocket) {
|
|
170
148
|
this.logger.info(
|
|
@@ -175,25 +153,20 @@ const Mercury = WebexPlugin.extend({
|
|
|
175
153
|
},
|
|
176
154
|
})
|
|
177
155
|
.then(() => {
|
|
178
|
-
this.logger.info(
|
|
179
|
-
`${this.namespace}: [shutdown] switchover completed successfully for ${sessionId}`
|
|
180
|
-
);
|
|
156
|
+
this.logger.info(`${this.namespace}: [shutdown] switchover completed successfully`);
|
|
181
157
|
})
|
|
182
158
|
.catch((err) => {
|
|
183
159
|
this.logger.info(
|
|
184
|
-
`${this.namespace}: [shutdown] switchover exhausted retries; will fall back to normal reconnection
|
|
160
|
+
`${this.namespace}: [shutdown] switchover exhausted retries; will fall back to normal reconnection`,
|
|
185
161
|
err
|
|
186
162
|
);
|
|
187
|
-
this._emit(
|
|
163
|
+
this._emit('event:mercury_shutdown_switchover_failed', {reason: err});
|
|
188
164
|
// Old socket will eventually close with 4001, triggering normal reconnection
|
|
189
165
|
});
|
|
190
166
|
} catch (e) {
|
|
191
|
-
this.logger.error(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
);
|
|
195
|
-
this._shutdownSwitchoverBackoffCalls.delete(sessionId);
|
|
196
|
-
this._emit(sessionId, 'event:mercury_shutdown_switchover_failed', {reason: e});
|
|
167
|
+
this.logger.error(`${this.namespace}: [shutdown] error during switchover`, e);
|
|
168
|
+
this._shutdownSwitchoverInProgress = false;
|
|
169
|
+
this._emit('event:mercury_shutdown_switchover_failed', {reason: e});
|
|
197
170
|
}
|
|
198
171
|
},
|
|
199
172
|
|
|
@@ -205,96 +178,29 @@ const Mercury = WebexPlugin.extend({
|
|
|
205
178
|
return this.lastError;
|
|
206
179
|
},
|
|
207
180
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
getSockets() {
|
|
213
|
-
return this.sockets;
|
|
214
|
-
},
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Get a specific socket by connection ID
|
|
218
|
-
* @param {string} sessionId - The connection identifier
|
|
219
|
-
* @returns {Socket|undefined} The socket instance or undefined if not found
|
|
220
|
-
*/
|
|
221
|
-
getSocket(sessionId = this.defaultSessionId) {
|
|
222
|
-
return this.sockets.get(sessionId);
|
|
223
|
-
},
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Check if any sockets are connected
|
|
227
|
-
* @returns {boolean} True if at least one socket is connected
|
|
228
|
-
*/
|
|
229
|
-
hasConnectedSockets() {
|
|
230
|
-
for (const socket of this.sockets.values()) {
|
|
231
|
-
if (socket && socket.connected) {
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return false;
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Check if any sockets are connecting
|
|
241
|
-
* @returns {boolean} True if at least one socket is connected
|
|
242
|
-
*/
|
|
243
|
-
hasConnectingSockets() {
|
|
244
|
-
for (const socket of this.sockets.values()) {
|
|
245
|
-
if (socket && socket.connecting) {
|
|
246
|
-
return true;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return false;
|
|
251
|
-
},
|
|
252
|
-
|
|
253
|
-
// @oneFlight
|
|
254
|
-
connect(webSocketUrl, sessionId = this.defaultSessionId) {
|
|
255
|
-
if (!this._connectPromises) this._connectPromises = new Map();
|
|
256
|
-
|
|
257
|
-
// First check if there's already a connection promise for this session
|
|
258
|
-
if (this._connectPromises.has(sessionId)) {
|
|
259
|
-
this.logger.info(
|
|
260
|
-
`${this.namespace}: connection ${sessionId} already in progress, returning existing promise`
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
return this._connectPromises.get(sessionId);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const sessionSocket = this.sockets.get(sessionId);
|
|
267
|
-
if (sessionSocket?.connected || sessionSocket?.connecting) {
|
|
268
|
-
this.logger.info(
|
|
269
|
-
`${this.namespace}: connection ${sessionId} already connected, will not connect again`
|
|
270
|
-
);
|
|
181
|
+
@oneFlight
|
|
182
|
+
connect(webSocketUrl) {
|
|
183
|
+
if (this.connected) {
|
|
184
|
+
this.logger.info(`${this.namespace}: already connected, will not connect again`);
|
|
271
185
|
|
|
272
186
|
return Promise.resolve();
|
|
273
187
|
}
|
|
274
188
|
|
|
275
189
|
this.connecting = true;
|
|
276
190
|
|
|
277
|
-
this.logger.info(`${this.namespace}: starting connection attempt
|
|
191
|
+
this.logger.info(`${this.namespace}: starting connection attempt`);
|
|
278
192
|
this.logger.info(
|
|
279
193
|
`${this.namespace}: debug_mercury_logging stack: `,
|
|
280
194
|
new Error('debug_mercury_logging').stack
|
|
281
195
|
);
|
|
282
196
|
|
|
283
|
-
|
|
197
|
+
return Promise.resolve(
|
|
284
198
|
this.webex.internal.device.registered || this.webex.internal.device.register()
|
|
285
|
-
)
|
|
286
|
-
.
|
|
287
|
-
this.logger.info(`${this.namespace}: connecting ${sessionId}`);
|
|
288
|
-
|
|
289
|
-
return this._connectWithBackoff(webSocketUrl, sessionId);
|
|
290
|
-
})
|
|
291
|
-
.finally(() => {
|
|
292
|
-
this._connectPromises.delete(sessionId);
|
|
293
|
-
});
|
|
199
|
+
).then(() => {
|
|
200
|
+
this.logger.info(`${this.namespace}: connecting`);
|
|
294
201
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return connectPromise;
|
|
202
|
+
return this._connectWithBackoff(webSocketUrl);
|
|
203
|
+
});
|
|
298
204
|
},
|
|
299
205
|
|
|
300
206
|
logout() {
|
|
@@ -304,7 +210,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
304
210
|
new Error('debug_mercury_logging').stack
|
|
305
211
|
);
|
|
306
212
|
|
|
307
|
-
return this.
|
|
213
|
+
return this.disconnect(
|
|
308
214
|
this.config.beforeLogoutOptionsCloseReason &&
|
|
309
215
|
!normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason)
|
|
310
216
|
? {code: 3050, reason: this.config.beforeLogoutOptionsCloseReason}
|
|
@@ -312,63 +218,26 @@ const Mercury = WebexPlugin.extend({
|
|
|
312
218
|
);
|
|
313
219
|
},
|
|
314
220
|
|
|
315
|
-
|
|
316
|
-
disconnect(options
|
|
221
|
+
@oneFlight
|
|
222
|
+
disconnect(options) {
|
|
317
223
|
return new Promise((resolve) => {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this.
|
|
321
|
-
backoffCall.abort();
|
|
322
|
-
this.backoffCalls.delete(sessionId);
|
|
323
|
-
}
|
|
324
|
-
const shutdownSwitchoverBackoffCalls = this._shutdownSwitchoverBackoffCalls.get(sessionId);
|
|
325
|
-
if (shutdownSwitchoverBackoffCalls) {
|
|
326
|
-
this.logger.info(`${this.namespace}: aborting shutdown switchover connection ${sessionId}`);
|
|
327
|
-
shutdownSwitchoverBackoffCalls.abort();
|
|
328
|
-
this._shutdownSwitchoverBackoffCalls.delete(sessionId);
|
|
329
|
-
}
|
|
330
|
-
// Clean up any pending connection promises
|
|
331
|
-
if (this._connectPromises) {
|
|
332
|
-
this._connectPromises.delete(sessionId);
|
|
224
|
+
if (this.backoffCall) {
|
|
225
|
+
this.logger.info(`${this.namespace}: aborting connection`);
|
|
226
|
+
this.backoffCall.abort();
|
|
333
227
|
}
|
|
334
228
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (sessionSocket) {
|
|
339
|
-
sessionSocket.removeAllListeners('message');
|
|
340
|
-
sessionSocket.connecting = false;
|
|
341
|
-
sessionSocket.connected = false;
|
|
342
|
-
this.once(sessionId === this.defaultSessionId ? 'offline' : `offline${suffix}`, resolve);
|
|
343
|
-
resolve(sessionSocket.close(options || undefined));
|
|
229
|
+
if (this._shutdownSwitchoverBackoffCall) {
|
|
230
|
+
this.logger.info(`${this.namespace}: aborting shutdown switchover`);
|
|
231
|
+
this._shutdownSwitchoverBackoffCall.abort();
|
|
344
232
|
}
|
|
345
|
-
resolve();
|
|
346
233
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Disconnect all socket connections
|
|
354
|
-
* @param {object} options - Close options
|
|
355
|
-
* @returns {Promise} Promise that resolves when all connections are closed
|
|
356
|
-
*/
|
|
357
|
-
disconnectAll(options) {
|
|
358
|
-
const disconnectPromises = [];
|
|
359
|
-
|
|
360
|
-
for (const sessionId of this.sockets.keys()) {
|
|
361
|
-
disconnectPromises.push(this.disconnect(options, sessionId));
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return Promise.all(disconnectPromises).then(() => {
|
|
365
|
-
this.connected = false;
|
|
366
|
-
this.sockets.clear();
|
|
367
|
-
this.backoffCalls.clear();
|
|
368
|
-
// Clear connection promises to prevent stale promises
|
|
369
|
-
if (this._connectPromises) {
|
|
370
|
-
this._connectPromises.clear();
|
|
234
|
+
if (this.socket) {
|
|
235
|
+
this.socket.removeAllListeners('message');
|
|
236
|
+
this.once('offline', resolve);
|
|
237
|
+
resolve(this.socket.close(options || undefined));
|
|
371
238
|
}
|
|
239
|
+
|
|
240
|
+
resolve();
|
|
372
241
|
});
|
|
373
242
|
},
|
|
374
243
|
|
|
@@ -408,7 +277,26 @@ const Mercury = WebexPlugin.extend({
|
|
|
408
277
|
.getFeature('developer', 'web-high-availability')
|
|
409
278
|
.then((haMessagingEnabled) => {
|
|
410
279
|
if (haMessagingEnabled) {
|
|
411
|
-
|
|
280
|
+
let highPrioritySocketUrl;
|
|
281
|
+
try {
|
|
282
|
+
highPrioritySocketUrl =
|
|
283
|
+
this.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
|
|
284
|
+
} catch (e) {
|
|
285
|
+
this.logger.warn(`${this.namespace}: error converting to high priority url`, e);
|
|
286
|
+
}
|
|
287
|
+
if (!highPrioritySocketUrl) {
|
|
288
|
+
const hostFromUrl = url.parse(webSocketUrl, true)?.host;
|
|
289
|
+
const isValidHost = this.webex.internal.services.isValidHost(hostFromUrl);
|
|
290
|
+
if (!isValidHost) {
|
|
291
|
+
this.logger.error(
|
|
292
|
+
`${this.namespace}: host ${hostFromUrl} is not a valid host from host catalog`
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
return '';
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return highPrioritySocketUrl || webSocketUrl;
|
|
412
300
|
}
|
|
413
301
|
|
|
414
302
|
return webSocketUrl;
|
|
@@ -418,6 +306,9 @@ const Mercury = WebexPlugin.extend({
|
|
|
418
306
|
})
|
|
419
307
|
.then(() => this.webex.internal.feature.getFeature('developer', 'web-shared-mercury'))
|
|
420
308
|
.then((webSharedMercury) => {
|
|
309
|
+
if (!webSocketUrl) {
|
|
310
|
+
return '';
|
|
311
|
+
}
|
|
421
312
|
webSocketUrl = url.parse(webSocketUrl, true);
|
|
422
313
|
Object.assign(webSocketUrl.query, {
|
|
423
314
|
outboundWireFormat: 'text',
|
|
@@ -443,22 +334,17 @@ const Mercury = WebexPlugin.extend({
|
|
|
443
334
|
});
|
|
444
335
|
},
|
|
445
336
|
|
|
446
|
-
_attemptConnection(socketUrl,
|
|
337
|
+
_attemptConnection(socketUrl, callback, options = {}) {
|
|
447
338
|
const {isShutdownSwitchover = false, onSuccess = null} = options;
|
|
448
339
|
|
|
449
340
|
const socket = new Socket();
|
|
450
|
-
socket.connecting = true;
|
|
451
341
|
let newWSUrl;
|
|
452
342
|
|
|
453
|
-
this._attachSocketEventListeners(socket
|
|
454
|
-
|
|
455
|
-
const backoffCall = isShutdownSwitchover
|
|
456
|
-
? this._shutdownSwitchoverBackoffCalls.get(sessionId)
|
|
457
|
-
: this.backoffCalls.get(sessionId);
|
|
343
|
+
this._attachSocketEventListeners(socket);
|
|
458
344
|
|
|
459
345
|
// Check appropriate backoff call based on connection type
|
|
460
|
-
if (isShutdownSwitchover && !
|
|
461
|
-
const msg = `${this.namespace}: prevent socket open when switchover backoff call no longer defined
|
|
346
|
+
if (isShutdownSwitchover && !this._shutdownSwitchoverBackoffCall) {
|
|
347
|
+
const msg = `${this.namespace}: prevent socket open when switchover backoff call no longer defined`;
|
|
462
348
|
const err = new Error(msg);
|
|
463
349
|
|
|
464
350
|
this.logger.info(msg);
|
|
@@ -469,8 +355,8 @@ const Mercury = WebexPlugin.extend({
|
|
|
469
355
|
return Promise.reject(err);
|
|
470
356
|
}
|
|
471
357
|
|
|
472
|
-
if (!isShutdownSwitchover && !backoffCall) {
|
|
473
|
-
const msg = `${this.namespace}: prevent socket open when backoffCall no longer defined
|
|
358
|
+
if (!isShutdownSwitchover && !this.backoffCall) {
|
|
359
|
+
const msg = `${this.namespace}: prevent socket open when backoffCall no longer defined`;
|
|
474
360
|
const err = new Error(msg);
|
|
475
361
|
|
|
476
362
|
this.logger.info(msg);
|
|
@@ -484,17 +370,16 @@ const Mercury = WebexPlugin.extend({
|
|
|
484
370
|
// For shutdown switchover, don't set socket yet (make-before-break)
|
|
485
371
|
// For normal connection, set socket before opening to allow disconnect() to close it
|
|
486
372
|
if (!isShutdownSwitchover) {
|
|
487
|
-
this.
|
|
373
|
+
this.socket = socket;
|
|
488
374
|
}
|
|
489
375
|
|
|
490
|
-
return this._prepareAndOpenSocket(socket, socketUrl,
|
|
376
|
+
return this._prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover)
|
|
491
377
|
.then((webSocketUrl) => {
|
|
492
378
|
newWSUrl = webSocketUrl;
|
|
493
|
-
|
|
494
379
|
this.logger.info(
|
|
495
380
|
`${this.namespace}: ${
|
|
496
381
|
isShutdownSwitchover ? '[shutdown] switchover' : ''
|
|
497
|
-
} connected to mercury, success, action: connected
|
|
382
|
+
} connected to mercury, success, action: connected, url: ${newWSUrl}`
|
|
498
383
|
);
|
|
499
384
|
|
|
500
385
|
// Custom success handler for shutdown switchover
|
|
@@ -521,10 +406,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
521
406
|
.catch((reason) => {
|
|
522
407
|
// For shutdown, simpler error handling - just callback for retry
|
|
523
408
|
if (isShutdownSwitchover) {
|
|
524
|
-
this.logger.info(
|
|
525
|
-
`${this.namespace}: [shutdown] switchover attempt failed for ${sessionId}`,
|
|
526
|
-
reason
|
|
527
|
-
);
|
|
409
|
+
this.logger.info(`${this.namespace}: [shutdown] switchover attempt failed`, reason);
|
|
528
410
|
|
|
529
411
|
return callback(reason);
|
|
530
412
|
}
|
|
@@ -532,36 +414,30 @@ const Mercury = WebexPlugin.extend({
|
|
|
532
414
|
// Normal connection error handling (existing complex logic)
|
|
533
415
|
this.lastError = reason; // remember the last error
|
|
534
416
|
|
|
535
|
-
const backoffCall = this.backoffCalls.get(sessionId);
|
|
536
417
|
// Suppress connection errors that appear to be network related. This
|
|
537
418
|
// may end up suppressing metrics during outages, but we might not care
|
|
538
419
|
// (especially since many of our outages happen in a way that client
|
|
539
420
|
// metrics can't be trusted).
|
|
540
|
-
if (reason.code !== 1006 && backoffCall && backoffCall?.getNumRetries() > 0) {
|
|
541
|
-
this._emit(
|
|
542
|
-
sessionId,
|
|
543
|
-
retries: backoffCall?.getNumRetries(),
|
|
544
|
-
});
|
|
421
|
+
if (reason.code !== 1006 && this.backoffCall && this.backoffCall?.getNumRetries() > 0) {
|
|
422
|
+
this._emit('connection_failed', reason, {retries: this.backoffCall?.getNumRetries()});
|
|
545
423
|
}
|
|
546
424
|
this.logger.info(
|
|
547
|
-
`${this.namespace}: connection attempt failed
|
|
425
|
+
`${this.namespace}: connection attempt failed`,
|
|
548
426
|
reason,
|
|
549
|
-
backoffCall?.getNumRetries() === 0 ? reason.stack : ''
|
|
427
|
+
this.backoffCall?.getNumRetries() === 0 ? reason.stack : ''
|
|
550
428
|
);
|
|
551
429
|
// UnknownResponse is produced by IE for any 4XXX; treated it like a bad
|
|
552
430
|
// web socket url and let WDM handle the token checking
|
|
553
431
|
if (reason instanceof UnknownResponse) {
|
|
554
432
|
this.logger.info(
|
|
555
|
-
`${this.namespace}: received unknown response code
|
|
433
|
+
`${this.namespace}: received unknown response code, refreshing device registration`
|
|
556
434
|
);
|
|
557
435
|
|
|
558
436
|
return this.webex.internal.device.refresh().then(() => callback(reason));
|
|
559
437
|
}
|
|
560
438
|
// NotAuthorized implies expired token
|
|
561
439
|
if (reason instanceof NotAuthorized) {
|
|
562
|
-
this.logger.info(
|
|
563
|
-
`${this.namespace}: received authorization error for ${sessionId}, reauthorizing`
|
|
564
|
-
);
|
|
440
|
+
this.logger.info(`${this.namespace}: received authorization error, reauthorizing`);
|
|
565
441
|
|
|
566
442
|
return this.webex.credentials.refresh({force: true}).then(() => callback(reason));
|
|
567
443
|
}
|
|
@@ -574,10 +450,8 @@ const Mercury = WebexPlugin.extend({
|
|
|
574
450
|
// BadRequest implies current credentials are for a Service Account
|
|
575
451
|
// Forbidden implies current user is not entitle for Webex
|
|
576
452
|
if (reason instanceof BadRequest || reason instanceof Forbidden) {
|
|
577
|
-
this.logger.warn(
|
|
578
|
-
|
|
579
|
-
);
|
|
580
|
-
backoffCall?.abort();
|
|
453
|
+
this.logger.warn(`${this.namespace}: received unrecoverable response from mercury`);
|
|
454
|
+
this.backoffCall.abort();
|
|
581
455
|
|
|
582
456
|
return callback(reason);
|
|
583
457
|
}
|
|
@@ -587,7 +461,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
587
461
|
.then((haMessagingEnabled) => {
|
|
588
462
|
if (haMessagingEnabled) {
|
|
589
463
|
this.logger.info(
|
|
590
|
-
`${this.namespace}: received a generic connection error
|
|
464
|
+
`${this.namespace}: received a generic connection error, will try to connect to another datacenter. failed, action: 'failed', url: ${newWSUrl} error: ${reason.message}`
|
|
591
465
|
);
|
|
592
466
|
|
|
593
467
|
return this.webex.internal.services.markFailedUrl(newWSUrl);
|
|
@@ -601,15 +475,12 @@ const Mercury = WebexPlugin.extend({
|
|
|
601
475
|
return callback(reason);
|
|
602
476
|
})
|
|
603
477
|
.catch((reason) => {
|
|
604
|
-
this.logger.error(
|
|
605
|
-
`${this.namespace}: failed to handle connection failure for ${sessionId}`,
|
|
606
|
-
reason
|
|
607
|
-
);
|
|
478
|
+
this.logger.error(`${this.namespace}: failed to handle connection failure`, reason);
|
|
608
479
|
callback(reason);
|
|
609
480
|
});
|
|
610
481
|
},
|
|
611
482
|
|
|
612
|
-
_prepareAndOpenSocket(socket, socketUrl,
|
|
483
|
+
_prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover = false) {
|
|
613
484
|
const logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
|
|
614
485
|
|
|
615
486
|
return Promise.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(
|
|
@@ -632,31 +503,30 @@ const Mercury = WebexPlugin.extend({
|
|
|
632
503
|
options = {...options, ...this.webex.config.defaultMercuryOptions};
|
|
633
504
|
}
|
|
634
505
|
|
|
635
|
-
|
|
636
|
-
// the socket if it is in the process of being opened.
|
|
637
|
-
this.sockets.set(sessionId, socket);
|
|
638
|
-
this.socket = this.sockets.get(this.defaultSessionId) || socket;
|
|
639
|
-
|
|
640
|
-
this.logger.info(`${this.namespace} ${logPrefix} url for ${sessionId}: ${webSocketUrl}`);
|
|
506
|
+
this.logger.info(`${this.namespace}: ${logPrefix} url: ${webSocketUrl}`);
|
|
641
507
|
|
|
642
508
|
return socket.open(webSocketUrl, options).then(() => webSocketUrl);
|
|
643
509
|
}
|
|
644
510
|
);
|
|
645
511
|
},
|
|
646
512
|
|
|
647
|
-
_connectWithBackoff(webSocketUrl,
|
|
513
|
+
_connectWithBackoff(webSocketUrl, context = {}) {
|
|
648
514
|
const {isShutdownSwitchover = false, attemptOptions = {}} = context;
|
|
649
515
|
|
|
650
516
|
return new Promise((resolve, reject) => {
|
|
651
|
-
// eslint gets confused about whether call is actually used
|
|
517
|
+
// eslint gets confused about whether or not call is actually used
|
|
652
518
|
// eslint-disable-next-line prefer-const
|
|
653
519
|
let call;
|
|
654
|
-
const onComplete = (err
|
|
520
|
+
const onComplete = (err) => {
|
|
521
|
+
// Clear state flags based on connection type
|
|
655
522
|
if (isShutdownSwitchover) {
|
|
656
|
-
this.
|
|
523
|
+
this._shutdownSwitchoverInProgress = false;
|
|
524
|
+
this._shutdownSwitchoverBackoffCall = undefined;
|
|
657
525
|
} else {
|
|
658
|
-
this.
|
|
526
|
+
this.connecting = false;
|
|
527
|
+
this.backoffCall = undefined;
|
|
659
528
|
}
|
|
529
|
+
|
|
660
530
|
if (err) {
|
|
661
531
|
const msg = isShutdownSwitchover
|
|
662
532
|
? `[shutdown] switchover failed after ${call.getNumRetries()} retries`
|
|
@@ -668,36 +538,26 @@ const Mercury = WebexPlugin.extend({
|
|
|
668
538
|
|
|
669
539
|
return reject(err);
|
|
670
540
|
}
|
|
671
|
-
|
|
672
|
-
const sessionSocket = this.sockets.get(sid);
|
|
673
|
-
if (sessionSocket) {
|
|
674
|
-
sessionSocket.connecting = false;
|
|
675
|
-
sessionSocket.connected = true;
|
|
676
|
-
}
|
|
541
|
+
|
|
677
542
|
// Default success handling for normal connections
|
|
678
543
|
if (!isShutdownSwitchover) {
|
|
679
|
-
this.
|
|
680
|
-
this.connected = this.hasConnectedSockets();
|
|
544
|
+
this.connected = true;
|
|
681
545
|
this.hasEverConnected = true;
|
|
682
|
-
this._emit(
|
|
546
|
+
this._emit('online');
|
|
683
547
|
this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
|
|
684
548
|
}
|
|
685
549
|
|
|
686
550
|
return resolve();
|
|
687
551
|
};
|
|
552
|
+
|
|
688
553
|
// eslint-disable-next-line prefer-reflect
|
|
689
|
-
call = backoff.call(
|
|
690
|
-
(
|
|
691
|
-
|
|
692
|
-
const logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
|
|
554
|
+
call = backoff.call((callback) => {
|
|
555
|
+
const attemptNum = call.getNumRetries();
|
|
556
|
+
const logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
|
|
693
557
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
this._attemptConnection(webSocketUrl, sessionId, callback, attemptOptions);
|
|
698
|
-
},
|
|
699
|
-
(err) => onComplete(err, sessionId)
|
|
700
|
-
);
|
|
558
|
+
this.logger.info(`${this.namespace}: executing ${logPrefix} attempt ${attemptNum}`);
|
|
559
|
+
this._attemptConnection(webSocketUrl, callback, attemptOptions);
|
|
560
|
+
}, onComplete);
|
|
701
561
|
|
|
702
562
|
call.setStrategy(
|
|
703
563
|
new backoff.ExponentialStrategy({
|
|
@@ -716,32 +576,23 @@ const Mercury = WebexPlugin.extend({
|
|
|
716
576
|
call.failAfter(this.config.maxRetries);
|
|
717
577
|
}
|
|
718
578
|
|
|
719
|
-
// Store the call BEFORE setting up event handlers to prevent race conditions
|
|
720
|
-
// Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
|
|
721
|
-
if (isShutdownSwitchover) {
|
|
722
|
-
this._shutdownSwitchoverBackoffCalls.set(sessionId, call);
|
|
723
|
-
} else {
|
|
724
|
-
this.backoffCalls.set(sessionId, call);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
579
|
call.on('abort', () => {
|
|
728
580
|
const msg = isShutdownSwitchover ? 'Shutdown Switchover' : 'Connection';
|
|
729
581
|
|
|
730
|
-
this.logger.info(`${this.namespace}: ${msg} aborted
|
|
731
|
-
reject(new Error(`Mercury ${msg} Aborted
|
|
582
|
+
this.logger.info(`${this.namespace}: ${msg} aborted`);
|
|
583
|
+
reject(new Error(`Mercury ${msg} Aborted`));
|
|
732
584
|
});
|
|
733
585
|
|
|
734
586
|
call.on('callback', (err) => {
|
|
735
587
|
if (err) {
|
|
736
588
|
const number = call.getNumRetries();
|
|
737
589
|
const delay = Math.min(call.strategy_.nextBackoffDelay_, this.config.backoffTimeMax);
|
|
738
|
-
|
|
739
590
|
const logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : '';
|
|
740
591
|
|
|
741
592
|
this.logger.info(
|
|
742
593
|
`${this.namespace}: ${logPrefix} failed to connect; attempting retry ${
|
|
743
594
|
number + 1
|
|
744
|
-
} in ${delay} ms
|
|
595
|
+
} in ${delay} ms`
|
|
745
596
|
);
|
|
746
597
|
/* istanbul ignore if */
|
|
747
598
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -750,52 +601,30 @@ const Mercury = WebexPlugin.extend({
|
|
|
750
601
|
|
|
751
602
|
return;
|
|
752
603
|
}
|
|
753
|
-
this.logger.info(`${this.namespace}: connected
|
|
604
|
+
this.logger.info(`${this.namespace}: connected`);
|
|
754
605
|
});
|
|
755
606
|
|
|
607
|
+
// Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
|
|
608
|
+
if (isShutdownSwitchover) {
|
|
609
|
+
this._shutdownSwitchoverBackoffCall = call;
|
|
610
|
+
} else {
|
|
611
|
+
this.backoffCall = call;
|
|
612
|
+
}
|
|
613
|
+
|
|
756
614
|
call.start();
|
|
757
615
|
});
|
|
758
616
|
},
|
|
759
617
|
|
|
760
618
|
_emit(...args) {
|
|
761
619
|
try {
|
|
762
|
-
|
|
763
|
-
return;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
// New signature: _emit(sessionId, eventName, ...rest)
|
|
767
|
-
// Backwards compatibility: if the first arg isn't a known sessionId (or defaultSessionId),
|
|
768
|
-
// treat the call as the old signature and forward directly to trigger(...)
|
|
769
|
-
const [first, second, ...rest] = args;
|
|
770
|
-
|
|
771
|
-
if (
|
|
772
|
-
typeof first === 'string' &&
|
|
773
|
-
(this.sockets.has(first) || first === this.defaultSessionId) &&
|
|
774
|
-
typeof second === 'string'
|
|
775
|
-
) {
|
|
776
|
-
const sessionId = first;
|
|
777
|
-
const eventName = second;
|
|
778
|
-
const suffix = sessionId === this.defaultSessionId ? '' : `:${sessionId}`;
|
|
779
|
-
|
|
780
|
-
this.trigger(`${eventName}${suffix}`, ...rest);
|
|
781
|
-
} else {
|
|
782
|
-
// Old usage: _emit(eventName, ...args)
|
|
783
|
-
this.trigger(...args);
|
|
784
|
-
}
|
|
620
|
+
this.trigger(...args);
|
|
785
621
|
} catch (error) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
args
|
|
793
|
-
);
|
|
794
|
-
} catch (logError) {
|
|
795
|
-
// If even logging fails, just ignore to prevent cascading errors during cleanup
|
|
796
|
-
// eslint-disable-next-line no-console
|
|
797
|
-
console.error('Mercury _emit error handling failed:', logError);
|
|
798
|
-
}
|
|
622
|
+
this.logger.error(
|
|
623
|
+
`${this.namespace}: error occurred in event handler:`,
|
|
624
|
+
error,
|
|
625
|
+
' with args: ',
|
|
626
|
+
args
|
|
627
|
+
);
|
|
799
628
|
}
|
|
800
629
|
},
|
|
801
630
|
|
|
@@ -819,40 +648,36 @@ const Mercury = WebexPlugin.extend({
|
|
|
819
648
|
return handlers;
|
|
820
649
|
},
|
|
821
650
|
|
|
822
|
-
_onclose(
|
|
651
|
+
_onclose(event, sourceSocket) {
|
|
823
652
|
// I don't see any way to avoid the complexity or statement count in here.
|
|
824
653
|
/* eslint complexity: [0] */
|
|
825
654
|
|
|
826
655
|
try {
|
|
656
|
+
const isActiveSocket = sourceSocket === this.socket;
|
|
827
657
|
const reason = event.reason && event.reason.toLowerCase();
|
|
828
|
-
let sessionSocket = this.sockets.get(sessionId);
|
|
829
|
-
let socketUrl;
|
|
830
|
-
event.sessionId = sessionId;
|
|
831
658
|
|
|
832
|
-
|
|
833
|
-
if (
|
|
659
|
+
let socketUrl;
|
|
660
|
+
if (isActiveSocket && this.socket) {
|
|
661
|
+
// Active socket closed - get URL from current socket reference
|
|
662
|
+
socketUrl = this.socket.url;
|
|
663
|
+
} else if (sourceSocket) {
|
|
664
|
+
// Old socket closed - get URL from the closed socket
|
|
834
665
|
socketUrl = sourceSocket.url;
|
|
835
666
|
}
|
|
836
|
-
this.sockets.delete(sessionId);
|
|
837
667
|
|
|
838
668
|
if (isActiveSocket) {
|
|
839
669
|
// Only tear down state if the currently active socket closed
|
|
840
|
-
if (
|
|
841
|
-
|
|
842
|
-
sessionSocket = null;
|
|
843
|
-
this._emit(sessionId, 'offline', event);
|
|
844
|
-
}
|
|
845
|
-
// Update overall connected status
|
|
846
|
-
this.connecting = this.hasConnectingSockets();
|
|
847
|
-
this.connected = this.hasConnectedSockets();
|
|
848
|
-
|
|
849
|
-
if (!this.connected) {
|
|
850
|
-
this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
|
|
670
|
+
if (this.socket) {
|
|
671
|
+
this.socket.removeAllListeners();
|
|
851
672
|
}
|
|
673
|
+
this.unset('socket');
|
|
674
|
+
this.connected = false;
|
|
675
|
+
this._emit('offline', event);
|
|
676
|
+
this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
|
|
852
677
|
} else {
|
|
853
678
|
// Old socket closed; do not flip connection state
|
|
854
679
|
this.logger.info(
|
|
855
|
-
`${this.namespace}: [shutdown] non-active socket closed, code=${event.code}
|
|
680
|
+
`${this.namespace}: [shutdown] non-active socket closed, code=${event.code}`
|
|
856
681
|
);
|
|
857
682
|
// Clean up listeners from old socket now that it's closed
|
|
858
683
|
if (sourceSocket) {
|
|
@@ -864,14 +689,14 @@ const Mercury = WebexPlugin.extend({
|
|
|
864
689
|
case 1003:
|
|
865
690
|
// metric: disconnect
|
|
866
691
|
this.logger.info(
|
|
867
|
-
`${this.namespace}: Mercury service rejected last message
|
|
692
|
+
`${this.namespace}: Mercury service rejected last message; will not reconnect: ${event.reason}`
|
|
868
693
|
);
|
|
869
|
-
if (isActiveSocket) this._emit(
|
|
694
|
+
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
870
695
|
break;
|
|
871
696
|
case 4000:
|
|
872
697
|
// metric: disconnect
|
|
873
|
-
this.logger.info(`${this.namespace}: socket
|
|
874
|
-
if (isActiveSocket) this._emit(
|
|
698
|
+
this.logger.info(`${this.namespace}: socket replaced; will not reconnect`);
|
|
699
|
+
if (isActiveSocket) this._emit('offline.replaced', event);
|
|
875
700
|
// If not active, nothing to do
|
|
876
701
|
break;
|
|
877
702
|
case 4001:
|
|
@@ -881,28 +706,26 @@ const Mercury = WebexPlugin.extend({
|
|
|
881
706
|
// to be replaced, but the switchover in _handleImminentShutdown failed.
|
|
882
707
|
// This is a permanent failure - do not reconnect.
|
|
883
708
|
this.logger.warn(
|
|
884
|
-
`${this.namespace}: active socket closed with 4001; shutdown switchover failed
|
|
709
|
+
`${this.namespace}: active socket closed with 4001; shutdown switchover failed`
|
|
885
710
|
);
|
|
886
|
-
this._emit(
|
|
711
|
+
this._emit('offline.permanent', event);
|
|
887
712
|
} else {
|
|
888
713
|
// Expected: old socket closed after successful switchover
|
|
889
714
|
this.logger.info(
|
|
890
|
-
`${this.namespace}: old socket closed with 4001 (replaced during shutdown); no reconnect needed
|
|
715
|
+
`${this.namespace}: old socket closed with 4001 (replaced during shutdown); no reconnect needed`
|
|
891
716
|
);
|
|
892
|
-
this._emit(
|
|
717
|
+
this._emit('offline.replaced', event);
|
|
893
718
|
}
|
|
894
719
|
break;
|
|
895
720
|
case 1001:
|
|
896
721
|
case 1005:
|
|
897
722
|
case 1006:
|
|
898
723
|
case 1011:
|
|
899
|
-
this.logger.info(`${this.namespace}: socket
|
|
724
|
+
this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
|
|
900
725
|
if (isActiveSocket) {
|
|
901
|
-
this._emit(
|
|
902
|
-
this.logger.info(
|
|
903
|
-
|
|
904
|
-
);
|
|
905
|
-
this._reconnect(socketUrl, sessionId);
|
|
726
|
+
this._emit('offline.transient', event);
|
|
727
|
+
this.logger.info(`${this.namespace}: [shutdown] reconnecting active socket to recover`);
|
|
728
|
+
this._reconnect(socketUrl);
|
|
906
729
|
}
|
|
907
730
|
// metric: disconnect
|
|
908
731
|
// if (code == 1011 && reason !== ping error) metric: unexpected disconnect
|
|
@@ -910,61 +733,51 @@ const Mercury = WebexPlugin.extend({
|
|
|
910
733
|
case 1000:
|
|
911
734
|
case 3050: // 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
|
|
912
735
|
if (normalReconnectReasons.includes(reason)) {
|
|
913
|
-
this.logger.info(`${this.namespace}: socket
|
|
736
|
+
this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
|
|
914
737
|
if (isActiveSocket) {
|
|
915
|
-
this._emit(
|
|
916
|
-
this.logger.info(
|
|
917
|
-
|
|
918
|
-
);
|
|
919
|
-
this._reconnect(socketUrl, sessionId);
|
|
738
|
+
this._emit('offline.transient', event);
|
|
739
|
+
this.logger.info(`${this.namespace}: [shutdown] reconnecting due to normal close`);
|
|
740
|
+
this._reconnect(socketUrl);
|
|
920
741
|
}
|
|
921
742
|
// metric: disconnect
|
|
922
743
|
// if (reason === done forced) metric: force closure
|
|
923
744
|
} else {
|
|
924
745
|
this.logger.info(
|
|
925
|
-
`${this.namespace}: socket
|
|
746
|
+
`${this.namespace}: socket disconnected; will not reconnect: ${event.reason}`
|
|
926
747
|
);
|
|
927
|
-
if (isActiveSocket) this._emit(
|
|
748
|
+
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
928
749
|
}
|
|
929
750
|
break;
|
|
930
751
|
default:
|
|
931
752
|
this.logger.info(
|
|
932
|
-
`${this.namespace}: socket
|
|
753
|
+
`${this.namespace}: socket disconnected unexpectedly; will not reconnect`
|
|
933
754
|
);
|
|
934
755
|
// unexpected disconnect
|
|
935
|
-
if (isActiveSocket) this._emit(
|
|
756
|
+
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
936
757
|
}
|
|
937
758
|
} catch (error) {
|
|
938
|
-
this.logger.error(
|
|
939
|
-
`${this.namespace}: error occurred in close handler for ${sessionId}`,
|
|
940
|
-
error
|
|
941
|
-
);
|
|
759
|
+
this.logger.error(`${this.namespace}: error occurred in close handler`, error);
|
|
942
760
|
}
|
|
943
761
|
},
|
|
944
762
|
|
|
945
|
-
_onmessage(
|
|
946
|
-
this._setTimeOffset(
|
|
763
|
+
_onmessage(event) {
|
|
764
|
+
this._setTimeOffset(event);
|
|
947
765
|
const envelope = event.data;
|
|
948
766
|
|
|
949
767
|
if (process.env.ENABLE_MERCURY_LOGGING) {
|
|
950
|
-
this.logger.debug(`${this.namespace}: message envelope
|
|
768
|
+
this.logger.debug(`${this.namespace}: message envelope: `, envelope);
|
|
951
769
|
}
|
|
952
770
|
|
|
953
|
-
envelope.sessionId = sessionId;
|
|
954
|
-
|
|
955
771
|
// Handle shutdown message shape: { type: 'shutdown' }
|
|
956
772
|
if (envelope && envelope.type === 'shutdown') {
|
|
957
|
-
this.logger.info(
|
|
958
|
-
|
|
959
|
-
);
|
|
960
|
-
this._emit(sessionId, 'event:mercury_shutdown_imminent', envelope);
|
|
773
|
+
this.logger.info(`${this.namespace}: [shutdown] imminent shutdown message received`);
|
|
774
|
+
this._emit('event:mercury_shutdown_imminent', envelope);
|
|
961
775
|
|
|
962
|
-
this._handleImminentShutdown(
|
|
776
|
+
this._handleImminentShutdown();
|
|
963
777
|
|
|
964
778
|
return Promise.resolve();
|
|
965
779
|
}
|
|
966
780
|
|
|
967
|
-
envelope.sessionId = sessionId;
|
|
968
781
|
const {data} = envelope;
|
|
969
782
|
|
|
970
783
|
this._applyOverrides(data);
|
|
@@ -979,7 +792,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
979
792
|
resolve((this.webex[namespace] || this.webex.internal[namespace])[name](data))
|
|
980
793
|
).catch((reason) =>
|
|
981
794
|
this.logger.error(
|
|
982
|
-
`${this.namespace}: error occurred in autowired event handler for ${data.eventType}
|
|
795
|
+
`${this.namespace}: error occurred in autowired event handler for ${data.eventType}`,
|
|
983
796
|
reason
|
|
984
797
|
)
|
|
985
798
|
);
|
|
@@ -987,35 +800,32 @@ const Mercury = WebexPlugin.extend({
|
|
|
987
800
|
Promise.resolve()
|
|
988
801
|
)
|
|
989
802
|
.then(() => {
|
|
990
|
-
this._emit(
|
|
803
|
+
this._emit('event', event.data);
|
|
991
804
|
const [namespace] = data.eventType.split('.');
|
|
992
805
|
|
|
993
806
|
if (namespace === data.eventType) {
|
|
994
|
-
this._emit(
|
|
807
|
+
this._emit(`event:${namespace}`, envelope);
|
|
995
808
|
} else {
|
|
996
|
-
this._emit(
|
|
997
|
-
this._emit(
|
|
809
|
+
this._emit(`event:${namespace}`, envelope);
|
|
810
|
+
this._emit(`event:${data.eventType}`, envelope);
|
|
998
811
|
}
|
|
999
812
|
})
|
|
1000
813
|
.catch((reason) => {
|
|
1001
|
-
this.logger.error(
|
|
1002
|
-
`${this.namespace}: error occurred processing socket message from ${sessionId}`,
|
|
1003
|
-
reason
|
|
1004
|
-
);
|
|
814
|
+
this.logger.error(`${this.namespace}: error occurred processing socket message`, reason);
|
|
1005
815
|
});
|
|
1006
816
|
},
|
|
1007
817
|
|
|
1008
|
-
_setTimeOffset(
|
|
818
|
+
_setTimeOffset(event) {
|
|
1009
819
|
const {wsWriteTimestamp} = event.data;
|
|
1010
820
|
if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
|
|
1011
821
|
this.mercuryTimeOffset = Date.now() - wsWriteTimestamp;
|
|
1012
822
|
}
|
|
1013
823
|
},
|
|
1014
824
|
|
|
1015
|
-
_reconnect(webSocketUrl
|
|
1016
|
-
this.logger.info(`${this.namespace}: reconnecting
|
|
825
|
+
_reconnect(webSocketUrl) {
|
|
826
|
+
this.logger.info(`${this.namespace}: reconnecting`);
|
|
1017
827
|
|
|
1018
|
-
return this.connect(webSocketUrl
|
|
828
|
+
return this.connect(webSocketUrl);
|
|
1019
829
|
},
|
|
1020
830
|
});
|
|
1021
831
|
|