@webex/internal-plugin-mercury 3.9.0-multi-llms.3 → 3.9.0-multi-llms.5

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/mercury.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
 
3
+ var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
4
+ var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
5
+ var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
6
+ var _Array$isArray = require("@babel/runtime-corejs2/core-js/array/is-array");
3
7
  var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
4
8
  var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
5
9
  var _Object$getOwnPropertyDescriptor2 = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
@@ -11,6 +15,7 @@ _Object$defineProperty(exports, "__esModule", {
11
15
  value: true
12
16
  });
13
17
  exports.default = void 0;
18
+ var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));
14
19
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
15
20
  var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
16
21
  var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
@@ -34,10 +39,14 @@ var _dec, _dec2, _obj;
34
39
  */
35
40
  function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor2(e, r).enumerable; })), t.push.apply(t, o); } return t; }
36
41
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor2(t, r)); }); } return e; }
42
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && o[_Symbol$iterator] || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
43
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
44
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
37
45
  var normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'pong mismatch'];
38
46
  var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mercury#listen(): Use Mercury#connect() instead'), _dec2 = (0, _common.deprecated)('Mercury#stopListening(): Use Mercury#disconnect() instead'), (_obj = {
39
47
  namespace: 'Mercury',
40
48
  lastError: undefined,
49
+ defaultSessionId: 'mercury-default-session',
41
50
  session: {
42
51
  connected: {
43
52
  default: false,
@@ -51,7 +60,18 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
51
60
  default: false,
52
61
  type: 'boolean'
53
62
  },
54
- socket: 'object',
63
+ sockets: {
64
+ default: function _default() {
65
+ return new _map.default();
66
+ },
67
+ type: 'object'
68
+ },
69
+ backoffCalls: {
70
+ default: function _default() {
71
+ return new _map.default();
72
+ },
73
+ type: 'object'
74
+ },
55
75
  localClusterServiceUrls: 'object',
56
76
  mercuryTimeOffset: {
57
77
  default: undefined,
@@ -109,41 +129,159 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
109
129
  getLastError: function getLastError() {
110
130
  return this.lastError;
111
131
  },
132
+ /**
133
+ * Get all active socket connections
134
+ * @returns {Map} Map of sessionId to socket instances
135
+ */
136
+ getSockets: function getSockets() {
137
+ return this.sockets;
138
+ },
139
+ /**
140
+ * Get a specific socket by connection ID
141
+ * @param {string} sessionId - The connection identifier
142
+ * @returns {Socket|undefined} The socket instance or undefined if not found
143
+ */
144
+ getSocket: function getSocket() {
145
+ var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
146
+ return this.sockets.get(sessionId);
147
+ },
148
+ /**
149
+ * Check if any sockets are connected
150
+ * @returns {boolean} True if at least one socket is connected
151
+ */
152
+ hasConnectedSockets: function hasConnectedSockets() {
153
+ var _iterator = _createForOfIteratorHelper(this.sockets.values()),
154
+ _step;
155
+ try {
156
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
157
+ var socket = _step.value;
158
+ if (socket && socket.connected) {
159
+ return true;
160
+ }
161
+ }
162
+ } catch (err) {
163
+ _iterator.e(err);
164
+ } finally {
165
+ _iterator.f();
166
+ }
167
+ return false;
168
+ },
169
+ /**
170
+ * Check if any sockets are connecting
171
+ * @returns {boolean} True if at least one socket is connected
172
+ */
173
+ hasConnectingSockets: function hasConnectingSockets() {
174
+ var _iterator2 = _createForOfIteratorHelper(this.sockets.values()),
175
+ _step2;
176
+ try {
177
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
178
+ var socket = _step2.value;
179
+ if (socket && socket.connecting) {
180
+ return true;
181
+ }
182
+ }
183
+ } catch (err) {
184
+ _iterator2.e(err);
185
+ } finally {
186
+ _iterator2.f();
187
+ }
188
+ return false;
189
+ },
190
+ // @oneFlight
112
191
  connect: function connect(webSocketUrl) {
113
192
  var _this2 = this;
114
- if (this.connected) {
115
- this.logger.info("".concat(this.namespace, ": already connected, will not connect again"));
193
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
194
+ if (!this._connectPromises) this._connectPromises = new _map.default();
195
+
196
+ // First check if there's already a connection promise for this session
197
+ if (this._connectPromises.has(sessionId)) {
198
+ this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already in progress, returning existing promise"));
199
+ return this._connectPromises.get(sessionId);
200
+ }
201
+ var sessionSocket = this.sockets.get(sessionId);
202
+ if (sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connected || sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connecting) {
203
+ this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already connected, will not connect again"));
116
204
  return _promise.default.resolve();
117
205
  }
118
206
  this.connecting = true;
119
- this.logger.info("".concat(this.namespace, ": starting connection attempt"));
207
+ this.logger.info("".concat(this.namespace, ": starting connection attempt for ").concat(sessionId));
120
208
  this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
121
- return _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
122
- _this2.logger.info("".concat(_this2.namespace, ": connecting"));
123
- return _this2._connectWithBackoff(webSocketUrl);
209
+ var connectPromise = _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
210
+ _this2.logger.info("".concat(_this2.namespace, ": connecting ").concat(sessionId));
211
+ return _this2._connectWithBackoff(webSocketUrl, sessionId);
212
+ }).finally(function () {
213
+ _this2._connectPromises.delete(sessionId);
124
214
  });
215
+ this._connectPromises.set(sessionId, connectPromise);
216
+ return connectPromise;
125
217
  },
126
218
  logout: function logout() {
127
219
  this.logger.info("".concat(this.namespace, ": logout() called"));
128
220
  this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
129
- return this.disconnect(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
221
+ return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
130
222
  code: 3050,
131
223
  reason: this.config.beforeLogoutOptionsCloseReason
132
224
  } : undefined);
133
225
  },
226
+ // @oneFlight
134
227
  disconnect: function disconnect(options) {
135
228
  var _this3 = this;
229
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
136
230
  return new _promise.default(function (resolve) {
137
- if (_this3.backoffCall) {
138
- _this3.logger.info("".concat(_this3.namespace, ": aborting connection"));
139
- _this3.backoffCall.abort();
231
+ var backoffCall = _this3.backoffCalls.get(sessionId);
232
+ if (backoffCall) {
233
+ _this3.logger.info("".concat(_this3.namespace, ": aborting connection ").concat(sessionId));
234
+ backoffCall.abort();
235
+ _this3.backoffCalls.delete(sessionId);
140
236
  }
141
- if (_this3.socket) {
142
- _this3.socket.removeAllListeners('message');
143
- _this3.once('offline', resolve);
144
- resolve(_this3.socket.close(options || undefined));
237
+
238
+ // Clean up any pending connection promises
239
+ if (_this3._connectPromises) {
240
+ _this3._connectPromises.delete(sessionId);
241
+ }
242
+ var sessionSocket = _this3.sockets.get(sessionId);
243
+ var suffix = sessionId === _this3.defaultSessionId ? '' : ":".concat(sessionId);
244
+ if (sessionSocket) {
245
+ sessionSocket.removeAllListeners('message');
246
+ sessionSocket.connecting = false;
247
+ sessionSocket.connected = false;
248
+ _this3.once(sessionId === _this3.defaultSessionId ? 'offline' : "offline".concat(suffix), resolve);
249
+ resolve(sessionSocket.close(options || undefined));
145
250
  }
146
251
  resolve();
252
+
253
+ // Update overall connected status
254
+ _this3.connected = _this3.hasConnectedSockets();
255
+ });
256
+ },
257
+ /**
258
+ * Disconnect all socket connections
259
+ * @param {object} options - Close options
260
+ * @returns {Promise} Promise that resolves when all connections are closed
261
+ */
262
+ disconnectAll: function disconnectAll(options) {
263
+ var _this4 = this;
264
+ var disconnectPromises = [];
265
+ var _iterator3 = _createForOfIteratorHelper(this.sockets.keys()),
266
+ _step3;
267
+ try {
268
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
269
+ var sessionId = _step3.value;
270
+ disconnectPromises.push(this.disconnect(options, sessionId));
271
+ }
272
+ } catch (err) {
273
+ _iterator3.e(err);
274
+ } finally {
275
+ _iterator3.f();
276
+ }
277
+ return _promise.default.all(disconnectPromises).then(function () {
278
+ _this4.connected = false;
279
+ _this4.sockets.clear();
280
+ _this4.backoffCalls.clear();
281
+ // Clear connection promises to prevent stale promises
282
+ if (_this4._connectPromises) {
283
+ _this4._connectPromises.clear();
284
+ }
147
285
  });
148
286
  },
149
287
  listen: function listen() {
@@ -167,19 +305,19 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
167
305
  });
168
306
  },
169
307
  _prepareUrl: function _prepareUrl(webSocketUrl) {
170
- var _this4 = this;
308
+ var _this5 = this;
171
309
  if (!webSocketUrl) {
172
310
  webSocketUrl = this.webex.internal.device.webSocketUrl;
173
311
  }
174
312
  return this.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
175
313
  if (haMessagingEnabled) {
176
- return _this4.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
314
+ return _this5.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
177
315
  }
178
316
  return webSocketUrl;
179
317
  }).then(function (wsUrl) {
180
318
  webSocketUrl = wsUrl;
181
319
  }).then(function () {
182
- return _this4.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
320
+ return _this5.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
183
321
  }).then(function (webSharedMercury) {
184
322
  webSocketUrl = _url.default.parse(webSocketUrl, true);
185
323
  (0, _assign.default)(webSocketUrl.query, {
@@ -194,104 +332,117 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
194
332
  });
195
333
  (0, _deleteProperty.default)(webSocketUrl.query, 'bufferStates');
196
334
  }
197
- if ((0, _lodash.get)(_this4, 'webex.config.device.ephemeral', false)) {
335
+ if ((0, _lodash.get)(_this5, 'webex.config.device.ephemeral', false)) {
198
336
  webSocketUrl.query.multipleConnections = true;
199
337
  }
200
338
  webSocketUrl.query.clientTimestamp = (0, _now.default)();
201
339
  return _url.default.format(webSocketUrl);
202
340
  });
203
341
  },
204
- _attemptConnection: function _attemptConnection(socketUrl, callback) {
205
- var _this5 = this;
342
+ _attemptConnection: function _attemptConnection(socketUrl, sessionId, callback) {
343
+ var _this6 = this;
206
344
  var socket = new _socket.default();
345
+ socket.connecting = true;
207
346
  var attemptWSUrl;
347
+ var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
208
348
  socket.on('close', function () {
209
- return _this5._onclose.apply(_this5, arguments);
349
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
350
+ args[_key] = arguments[_key];
351
+ }
352
+ return _this6._onclose.apply(_this6, [sessionId].concat(args));
210
353
  });
211
354
  socket.on('message', function () {
212
- return _this5._onmessage.apply(_this5, arguments);
355
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
356
+ args[_key2] = arguments[_key2];
357
+ }
358
+ return _this6._onmessage.apply(_this6, [sessionId].concat(args));
213
359
  });
214
360
  socket.on('pong', function () {
215
- return _this5._setTimeOffset.apply(_this5, arguments);
361
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
362
+ args[_key3] = arguments[_key3];
363
+ }
364
+ return _this6._setTimeOffset.apply(_this6, [sessionId].concat(args));
216
365
  });
217
366
  socket.on('sequence-mismatch', function () {
218
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
219
- args[_key] = arguments[_key];
367
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
368
+ args[_key4] = arguments[_key4];
220
369
  }
221
- return _this5._emit.apply(_this5, ['sequence-mismatch'].concat(args));
370
+ return _this6._emit.apply(_this6, ["sequence-mismatch".concat(suffix)].concat(args));
222
371
  });
223
372
  socket.on('ping-pong-latency', function () {
224
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
225
- args[_key2] = arguments[_key2];
373
+ for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
374
+ args[_key5] = arguments[_key5];
226
375
  }
227
- return _this5._emit.apply(_this5, ['ping-pong-latency'].concat(args));
376
+ return _this6._emit.apply(_this6, ["ping-pong-latency".concat(suffix)].concat(args));
228
377
  });
229
378
  _promise.default.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
230
379
  var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
231
380
  webSocketUrl = _ref2[0],
232
381
  token = _ref2[1];
233
- if (!_this5.backoffCall) {
234
- var msg = "".concat(_this5.namespace, ": prevent socket open when backoffCall no longer defined");
235
- _this5.logger.info(msg);
382
+ var backoffCall = _this6.backoffCalls.get(sessionId);
383
+ if (!backoffCall) {
384
+ var msg = "".concat(_this6.namespace, ": prevent socket open when backoffCall no longer defined for ").concat(sessionId);
385
+ _this6.logger.info(msg);
236
386
  return _promise.default.reject(new Error(msg));
237
387
  }
238
388
  attemptWSUrl = webSocketUrl;
239
389
  var options = {
240
- forceCloseDelay: _this5.config.forceCloseDelay,
241
- pingInterval: _this5.config.pingInterval,
242
- pongTimeout: _this5.config.pongTimeout,
390
+ forceCloseDelay: _this6.config.forceCloseDelay,
391
+ pingInterval: _this6.config.pingInterval,
392
+ pongTimeout: _this6.config.pongTimeout,
243
393
  token: token.toString(),
244
- trackingId: "".concat(_this5.webex.sessionId, "_").concat((0, _now.default)()),
245
- logger: _this5.logger
394
+ trackingId: "".concat(_this6.webex.sessionId, "_").concat(sessionId, "_").concat((0, _now.default)()),
395
+ logger: _this6.logger
246
396
  };
247
397
 
248
398
  // if the consumer has supplied request options use them
249
- if (_this5.webex.config.defaultMercuryOptions) {
250
- _this5.logger.info("".concat(_this5.namespace, ": setting custom options"));
251
- options = _objectSpread(_objectSpread({}, options), _this5.webex.config.defaultMercuryOptions);
399
+ if (_this6.webex.config.defaultMercuryOptions) {
400
+ _this6.logger.info("".concat(_this6.namespace, ": setting custom options for ").concat(sessionId));
401
+ options = _objectSpread(_objectSpread({}, options), _this6.webex.config.defaultMercuryOptions);
252
402
  }
253
403
 
254
404
  // Set the socket before opening it. This allows a disconnect() to close
255
405
  // the socket if it is in the process of being opened.
256
- _this5.socket = socket;
257
- _this5.logger.info("".concat(_this5.namespace, " connection url: ").concat(webSocketUrl));
406
+ _this6.sockets.set(sessionId, socket);
407
+ _this6.socket = _this6.sockets.get(_this6.defaultSessionId) || socket;
408
+ _this6.logger.info("".concat(_this6.namespace, " connection url for ").concat(sessionId, ": ").concat(webSocketUrl));
258
409
  return socket.open(webSocketUrl, options);
259
410
  }).then(function () {
260
- _this5.logger.info("".concat(_this5.namespace, ": connected to mercury, success, action: connected, url: ").concat(attemptWSUrl));
411
+ _this6.logger.info("".concat(_this6.namespace, ": connected to mercury, success, action: connected, sessionId: ").concat(sessionId, ", url: ").concat(attemptWSUrl));
261
412
  callback();
262
- return _this5.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
413
+ return _this6.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
263
414
  if (haMessagingEnabled) {
264
- return _this5.webex.internal.device.refresh();
415
+ return _this6.webex.internal.device.refresh();
265
416
  }
266
417
  return _promise.default.resolve();
267
418
  });
268
419
  }).catch(function (reason) {
269
- var _this5$backoffCall, _this5$backoffCall3;
270
- _this5.lastError = reason; // remember the last error
420
+ _this6.lastError = reason; // remember the last error
271
421
 
422
+ var backoffCall = _this6.backoffCalls.get(sessionId);
272
423
  // Suppress connection errors that appear to be network related. This
273
424
  // may end up suppressing metrics during outages, but we might not care
274
425
  // (especially since many of our outages happen in a way that client
275
426
  // metrics can't be trusted).
276
- if (reason.code !== 1006 && _this5.backoffCall && ((_this5$backoffCall = _this5.backoffCall) === null || _this5$backoffCall === void 0 ? void 0 : _this5$backoffCall.getNumRetries()) > 0) {
277
- var _this5$backoffCall2;
278
- _this5._emit('connection_failed', reason, {
279
- retries: (_this5$backoffCall2 = _this5.backoffCall) === null || _this5$backoffCall2 === void 0 ? void 0 : _this5$backoffCall2.getNumRetries()
427
+ if (reason.code !== 1006 && backoffCall && (backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()) > 0) {
428
+ _this6._emit("connection_failed".concat(suffix), reason, {
429
+ sessionId: sessionId,
430
+ retries: backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()
280
431
  });
281
432
  }
282
- _this5.logger.info("".concat(_this5.namespace, ": connection attempt failed"), reason, ((_this5$backoffCall3 = _this5.backoffCall) === null || _this5$backoffCall3 === void 0 ? void 0 : _this5$backoffCall3.getNumRetries()) === 0 ? reason.stack : '');
433
+ _this6.logger.info("".concat(_this6.namespace, ": connection attempt failed for ").concat(sessionId), reason, (backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()) === 0 ? reason.stack : '');
283
434
  // UnknownResponse is produced by IE for any 4XXX; treated it like a bad
284
435
  // web socket url and let WDM handle the token checking
285
436
  if (reason instanceof _errors.UnknownResponse) {
286
- _this5.logger.info("".concat(_this5.namespace, ": received unknown response code, refreshing device registration"));
287
- return _this5.webex.internal.device.refresh().then(function () {
437
+ _this6.logger.info("".concat(_this6.namespace, ": received unknown response code for ").concat(sessionId, ", refreshing device registration"));
438
+ return _this6.webex.internal.device.refresh().then(function () {
288
439
  return callback(reason);
289
440
  });
290
441
  }
291
442
  // NotAuthorized implies expired token
292
443
  if (reason instanceof _errors.NotAuthorized) {
293
- _this5.logger.info("".concat(_this5.namespace, ": received authorization error, reauthorizing"));
294
- return _this5.webex.credentials.refresh({
444
+ _this6.logger.info("".concat(_this6.namespace, ": received authorization error for ").concat(sessionId, ", reauthorizing"));
445
+ return _this6.webex.credentials.refresh({
295
446
  force: true
296
447
  }).then(function () {
297
448
  return callback(reason);
@@ -306,15 +457,15 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
306
457
  // BadRequest implies current credentials are for a Service Account
307
458
  // Forbidden implies current user is not entitle for Webex
308
459
  if (reason instanceof _errors.BadRequest || reason instanceof _errors.Forbidden) {
309
- _this5.logger.warn("".concat(_this5.namespace, ": received unrecoverable response from mercury"));
310
- _this5.backoffCall.abort();
460
+ _this6.logger.warn("".concat(_this6.namespace, ": received unrecoverable response from mercury for ").concat(sessionId));
461
+ backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.abort();
311
462
  return callback(reason);
312
463
  }
313
464
  if (reason instanceof _errors.ConnectionError) {
314
- return _this5.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
465
+ return _this6.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
315
466
  if (haMessagingEnabled) {
316
- _this5.logger.info("".concat(_this5.namespace, ": received a generic connection error, will try to connect to another datacenter. failed, action: 'failed', url: ").concat(attemptWSUrl, " error: ").concat(reason.message));
317
- return _this5.webex.internal.services.markFailedUrl(attemptWSUrl);
467
+ _this6.logger.info("".concat(_this6.namespace, ": received a generic connection error for ").concat(sessionId, ", will try to connect to another datacenter. failed, action: 'failed', url: ").concat(attemptWSUrl, " error: ").concat(reason.message));
468
+ return _this6.webex.internal.services.markFailedUrl(attemptWSUrl);
318
469
  }
319
470
  return null;
320
471
  }).then(function () {
@@ -323,73 +474,97 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
323
474
  }
324
475
  return callback(reason);
325
476
  }).catch(function (reason) {
326
- _this5.logger.error("".concat(_this5.namespace, ": failed to handle connection failure"), reason);
477
+ _this6.logger.error("".concat(_this6.namespace, ": failed to handle connection failure for ").concat(sessionId), reason);
327
478
  callback(reason);
328
479
  });
329
480
  },
330
- _connectWithBackoff: function _connectWithBackoff(webSocketUrl) {
331
- var _this6 = this;
481
+ _connectWithBackoff: function _connectWithBackoff(webSocketUrl, sessionId) {
482
+ var _this7 = this;
332
483
  return new _promise.default(function (resolve, reject) {
333
484
  // eslint gets confused about whether or not call is actually used
334
485
  // eslint-disable-next-line prefer-const
335
486
  var call;
336
487
  var onComplete = function onComplete(err) {
337
- _this6.connecting = false;
338
- _this6.backoffCall = undefined;
488
+ var sid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : sessionId;
489
+ _this7.backoffCalls.delete(sid);
339
490
  if (err) {
340
- _this6.logger.info("".concat(_this6.namespace, ": failed to connect after ").concat(call.getNumRetries(), " retries; log statement about next retry was inaccurate; ").concat(err));
491
+ _this7.logger.info("".concat(_this7.namespace, ": failed to connect ").concat(sid, " after ").concat(call.getNumRetries(), " retries; log statement about next retry was inaccurate; ").concat(err));
341
492
  return reject(err);
342
493
  }
343
- _this6.connected = true;
344
- _this6.hasEverConnected = true;
345
- _this6._emit('online');
346
- _this6.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
494
+ // Update overall connected status
495
+ var sessionSocket = _this7.sockets.get(sid);
496
+ if (sessionSocket) {
497
+ sessionSocket.connecting = false;
498
+ sessionSocket.connected = true;
499
+ }
500
+ // @ts-ignore
501
+ _this7.connecting = _this7.hasConnectingSockets();
502
+ _this7.connected = _this7.hasConnectedSockets();
503
+ _this7.hasEverConnected = true;
504
+ var suffix = sid === _this7.defaultSessionId ? '' : ":".concat(sid);
505
+ _this7._emit("online".concat(suffix), {
506
+ sessionId: sid
507
+ });
508
+ _this7.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
347
509
  return resolve();
348
510
  };
349
511
 
350
512
  // eslint-disable-next-line prefer-reflect
351
513
  call = _backoff.default.call(function (callback) {
352
- _this6.logger.info("".concat(_this6.namespace, ": executing connection attempt ").concat(call.getNumRetries()));
353
- _this6._attemptConnection(webSocketUrl, callback);
354
- }, onComplete);
514
+ _this7.logger.info("".concat(_this7.namespace, ": executing connection attempt ").concat(call.getNumRetries(), " for ").concat(sessionId));
515
+ _this7._attemptConnection(webSocketUrl, sessionId, callback);
516
+ }, function (err) {
517
+ return onComplete(err, sessionId);
518
+ });
355
519
  call.setStrategy(new _backoff.default.ExponentialStrategy({
356
- initialDelay: _this6.config.backoffTimeReset,
357
- maxDelay: _this6.config.backoffTimeMax
520
+ initialDelay: _this7.config.backoffTimeReset,
521
+ maxDelay: _this7.config.backoffTimeMax
358
522
  }));
359
- if (_this6.config.initialConnectionMaxRetries && !_this6.hasEverConnected) {
360
- call.failAfter(_this6.config.initialConnectionMaxRetries);
361
- } else if (_this6.config.maxRetries) {
362
- call.failAfter(_this6.config.maxRetries);
523
+ if (_this7.config.initialConnectionMaxRetries && !_this7.hasEverConnected) {
524
+ call.failAfter(_this7.config.initialConnectionMaxRetries);
525
+ } else if (_this7.config.maxRetries) {
526
+ call.failAfter(_this7.config.maxRetries);
363
527
  }
528
+
529
+ // Store the call BEFORE setting up event handlers to prevent race conditions
530
+ _this7.backoffCalls.set(sessionId, call);
364
531
  call.on('abort', function () {
365
- _this6.logger.info("".concat(_this6.namespace, ": connection aborted"));
366
- reject(new Error('Mercury Connection Aborted'));
532
+ _this7.logger.info("".concat(_this7.namespace, ": connection aborted for ").concat(sessionId));
533
+ reject(new Error("Mercury Connection Aborted for ".concat(sessionId)));
367
534
  });
368
535
  call.on('callback', function (err) {
369
536
  if (err) {
370
537
  var number = call.getNumRetries();
371
- var delay = Math.min(call.strategy_.nextBackoffDelay_, _this6.config.backoffTimeMax);
372
- _this6.logger.info("".concat(_this6.namespace, ": failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
538
+ var delay = Math.min(call.strategy_.nextBackoffDelay_, _this7.config.backoffTimeMax);
539
+ _this7.logger.info("".concat(_this7.namespace, ": failed to connect ").concat(sessionId, "; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
373
540
  /* istanbul ignore if */
374
541
  if (process.env.NODE_ENV === 'development') {
375
- _this6.logger.debug("".concat(_this6.namespace, ": "), err, err.stack);
542
+ _this7.logger.debug("".concat(_this7.namespace, ": "), err, err.stack);
376
543
  }
377
544
  return;
378
545
  }
379
- _this6.logger.info("".concat(_this6.namespace, ": connected"));
546
+ _this7.logger.info("".concat(_this7.namespace, ": connected ").concat(sessionId));
380
547
  });
381
548
  call.start();
382
- _this6.backoffCall = call;
383
549
  });
384
550
  },
385
551
  _emit: function _emit() {
386
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
387
- args[_key3] = arguments[_key3];
552
+ for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
553
+ args[_key6] = arguments[_key6];
388
554
  }
389
555
  try {
390
- this.trigger.apply(this, args);
556
+ // Validate args before processing
557
+ if (args && args.length > 0) {
558
+ this.trigger.apply(this, args);
559
+ }
391
560
  } catch (error) {
392
- this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
561
+ // Safely handle errors without causing additional issues during cleanup
562
+ try {
563
+ this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
564
+ } catch (logError) {
565
+ // If even logging fails, just ignore to prevent cascading errors during cleanup
566
+ console.error('Mercury _emit error handling failed:', logError);
567
+ }
393
568
  }
394
569
  },
395
570
  _getEventHandlers: function _getEventHandlers(eventType) {
@@ -410,36 +585,48 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
410
585
  }
411
586
  return handlers;
412
587
  },
413
- _onclose: function _onclose(event) {
588
+ _onclose: function _onclose(sessionId, event) {
414
589
  // I don't see any way to avoid the complexity or statement count in here.
415
590
  /* eslint complexity: [0] */
416
591
 
417
592
  try {
593
+ var _sessionSocket;
418
594
  var reason = event.reason && event.reason.toLowerCase();
419
- var socketUrl = this.socket.url;
420
- this.socket.removeAllListeners();
421
- this.unset('socket');
422
- this.connected = false;
423
- this._emit('offline', event);
424
- this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
595
+ var sessionSocket = this.sockets.get(sessionId);
596
+ var socketUrl = (_sessionSocket = sessionSocket) === null || _sessionSocket === void 0 ? void 0 : _sessionSocket.url;
597
+ var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
598
+ event.sessionId = sessionId;
599
+ this.sockets.delete(sessionId);
600
+ if (sessionSocket) {
601
+ sessionSocket.removeAllListeners();
602
+ sessionSocket = null;
603
+ this._emit("offline".concat(suffix), event);
604
+ }
605
+
606
+ // Update overall connected status
607
+ this.connecting = this.hasConnectingSockets();
608
+ this.connected = this.hasConnectedSockets();
609
+ if (!this.connected) {
610
+ this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
611
+ }
425
612
  switch (event.code) {
426
613
  case 1003:
427
614
  // metric: disconnect
428
- this.logger.info("".concat(this.namespace, ": Mercury service rejected last message; will not reconnect: ").concat(event.reason));
429
- this._emit('offline.permanent', event);
615
+ this.logger.info("".concat(this.namespace, ": Mercury service rejected last message for ").concat(sessionId, "; will not reconnect: ").concat(event.reason));
616
+ this._emit("offline.permanent".concat(suffix), event);
430
617
  break;
431
618
  case 4000:
432
619
  // metric: disconnect
433
- this.logger.info("".concat(this.namespace, ": socket replaced; will not reconnect"));
434
- this._emit('offline.replaced', event);
620
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " replaced; will not reconnect"));
621
+ this._emit("offline.replaced".concat(suffix), event);
435
622
  break;
436
623
  case 1001:
437
624
  case 1005:
438
625
  case 1006:
439
626
  case 1011:
440
- this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
441
- this._emit('offline.transient', event);
442
- this._reconnect(socketUrl);
627
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
628
+ this._emit("offline.transient".concat(suffix), event);
629
+ this._reconnect(socketUrl, sessionId);
443
630
  // metric: disconnect
444
631
  // if (code == 1011 && reason !== ping error) metric: unexpected disconnect
445
632
  break;
@@ -447,32 +634,33 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
447
634
  case 3050:
448
635
  // 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
449
636
  if (normalReconnectReasons.includes(reason)) {
450
- this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
451
- this._emit('offline.transient', event);
452
- this._reconnect(socketUrl);
637
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
638
+ this._emit("offline.transient".concat(suffix), event);
639
+ this._reconnect(socketUrl, sessionId);
453
640
  // metric: disconnect
454
641
  // if (reason === done forced) metric: force closure
455
642
  } else {
456
- this.logger.info("".concat(this.namespace, ": socket disconnected; will not reconnect: ").concat(event.reason));
457
- this._emit('offline.permanent', event);
643
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; will not reconnect: ").concat(event.reason));
644
+ this._emit("offline.permanent".concat(suffix), event);
458
645
  }
459
646
  break;
460
647
  default:
461
- this.logger.info("".concat(this.namespace, ": socket disconnected unexpectedly; will not reconnect"));
648
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected unexpectedly; will not reconnect"));
462
649
  // unexpected disconnect
463
- this._emit('offline.permanent', event);
650
+ this._emit("offline.permanent".concat(suffix), event);
464
651
  }
465
652
  } catch (error) {
466
- this.logger.error("".concat(this.namespace, ": error occurred in close handler"), error);
653
+ this.logger.error("".concat(this.namespace, ": error occurred in close handler for ").concat(sessionId), error);
467
654
  }
468
655
  },
469
- _onmessage: function _onmessage(event) {
470
- var _this7 = this;
471
- this._setTimeOffset(event);
656
+ _onmessage: function _onmessage(sessionId, event) {
657
+ var _this8 = this;
658
+ this._setTimeOffset(sessionId, event);
472
659
  var envelope = event.data;
473
660
  if (process.env.ENABLE_MERCURY_LOGGING) {
474
- this.logger.debug("".concat(this.namespace, ": message envelope: "), envelope);
661
+ this.logger.debug("".concat(this.namespace, ": message envelope from ").concat(sessionId, ": "), envelope);
475
662
  }
663
+ envelope.sessionId = sessionId;
476
664
  var data = envelope.data;
477
665
  this._applyOverrides(data);
478
666
  return this._getEventHandlers(data.eventType).reduce(function (promise, handler) {
@@ -480,37 +668,39 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
480
668
  var namespace = handler.namespace,
481
669
  name = handler.name;
482
670
  return new _promise.default(function (resolve) {
483
- return resolve((_this7.webex[namespace] || _this7.webex.internal[namespace])[name](data));
671
+ return resolve((_this8.webex[namespace] || _this8.webex.internal[namespace])[name](data));
484
672
  }).catch(function (reason) {
485
- return _this7.logger.error("".concat(_this7.namespace, ": error occurred in autowired event handler for ").concat(data.eventType), reason);
673
+ return _this8.logger.error("".concat(_this8.namespace, ": error occurred in autowired event handler for ").concat(data.eventType, " from ").concat(sessionId), reason);
486
674
  });
487
675
  });
488
676
  }, _promise.default.resolve()).then(function () {
489
- _this7._emit('event', event.data);
677
+ var suffix = sessionId === _this8.defaultSessionId ? '' : ":".concat(sessionId);
678
+ _this8._emit("event".concat(suffix), envelope);
490
679
  var _data$eventType$split = data.eventType.split('.'),
491
680
  _data$eventType$split2 = (0, _slicedToArray2.default)(_data$eventType$split, 1),
492
681
  namespace = _data$eventType$split2[0];
493
682
  if (namespace === data.eventType) {
494
- _this7._emit("event:".concat(namespace), envelope);
683
+ _this8._emit("event:".concat(namespace).concat(suffix), envelope);
495
684
  } else {
496
- _this7._emit("event:".concat(namespace), envelope);
497
- _this7._emit("event:".concat(data.eventType), envelope);
685
+ _this8._emit("event:".concat(namespace).concat(suffix), envelope);
686
+ _this8._emit("event:".concat(data.eventType).concat(suffix), envelope);
498
687
  }
499
688
  }).catch(function (reason) {
500
- _this7.logger.error("".concat(_this7.namespace, ": error occurred processing socket message"), reason);
689
+ _this8.logger.error("".concat(_this8.namespace, ": error occurred processing socket message from ").concat(sessionId), reason);
501
690
  });
502
691
  },
503
- _setTimeOffset: function _setTimeOffset(event) {
692
+ _setTimeOffset: function _setTimeOffset(sessionId, event) {
504
693
  var wsWriteTimestamp = event.data.wsWriteTimestamp;
505
694
  if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
506
695
  this.mercuryTimeOffset = (0, _now.default)() - wsWriteTimestamp;
507
696
  }
508
697
  },
509
698
  _reconnect: function _reconnect(webSocketUrl) {
510
- this.logger.info("".concat(this.namespace, ": reconnecting"));
511
- return this.connect(webSocketUrl);
699
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
700
+ this.logger.info("".concat(this.namespace, ": reconnecting ").concat(sessionId));
701
+ return this.connect(webSocketUrl, sessionId);
512
702
  },
513
- version: "3.9.0-multi-llms.3"
514
- }, ((0, _applyDecoratedDescriptor2.default)(_obj, "connect", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "connect"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "disconnect", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "disconnect"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "listen", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "listen"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "stopListening", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "stopListening"), _obj)), _obj)));
515
- var _default = exports.default = Mercury;
703
+ version: "3.9.0-multi-llms.5"
704
+ }, ((0, _applyDecoratedDescriptor2.default)(_obj, "listen", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "listen"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "stopListening", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "stopListening"), _obj)), _obj)));
705
+ var _default2 = exports.default = Mercury;
516
706
  //# sourceMappingURL=mercury.js.map