@webex/internal-plugin-mercury 3.12.0-auth-prejoin-fetch.1 → 3.12.0-llmrefactor.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/mercury.js CHANGED
@@ -1,9 +1,5 @@
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");
7
3
  var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
8
4
  var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
9
5
  var _Object$getOwnPropertyDescriptor2 = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
@@ -15,7 +11,6 @@ _Object$defineProperty(exports, "__esModule", {
15
11
  value: true
16
12
  });
17
13
  exports.default = void 0;
18
- var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));
19
14
  var _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
20
15
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
21
16
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
@@ -23,7 +18,6 @@ var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/objec
23
18
  var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
24
19
  var _deleteProperty = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/delete-property"));
25
20
  var _getOwnPropertyDescriptor = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor"));
26
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
27
21
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
28
22
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
29
23
  var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
@@ -41,15 +35,11 @@ var _dec, _dec2, _obj;
41
35
  */
42
36
  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; }
43
37
  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; }
44
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && r[_Symbol$iterator] || r["@@iterator"]; if (!t) { if (_Array$isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
45
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
46
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
47
38
  var normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'pong mismatch'];
48
39
  var MERCURY_CLOSE_4000_METRIC = 'JS_SDK_MERCURY_CLOSE_4000';
49
40
  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 = {
50
41
  namespace: 'Mercury',
51
42
  lastError: undefined,
52
- defaultSessionId: 'mercury-default-session',
53
43
  session: {
54
44
  connected: {
55
45
  default: false,
@@ -63,35 +53,19 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
63
53
  default: false,
64
54
  type: 'boolean'
65
55
  },
66
- sockets: {
67
- default: function _default() {
68
- return new _map.default();
69
- },
70
- type: 'object'
71
- },
72
- sessionWebSocketUrls: {
73
- default: function _default() {
74
- return new _map.default();
75
- },
76
- type: 'object'
77
- },
78
- backoffCalls: {
79
- default: function _default() {
80
- return new _map.default();
81
- },
82
- type: 'object'
83
- },
84
- _shutdownSwitchoverBackoffCalls: {
85
- default: function _default() {
86
- return new _map.default();
87
- },
88
- type: 'object'
89
- },
56
+ socket: 'object',
90
57
  localClusterServiceUrls: 'object',
91
58
  mercuryTimeOffset: {
92
59
  default: undefined,
93
60
  type: 'number'
94
- }
61
+ },
62
+ backoffCall: 'object',
63
+ _connectPromise: 'object',
64
+ _shutdownSwitchoverBackoffCall: 'object',
65
+ _shutdownSwitchoverId: 'string',
66
+ // Store the resolved (pre-proxy) URL so reconnection uses a catalog-valid host
67
+ // instead of the potentially rewritten socket.url from an interceptor.
68
+ resolvedWebSocketUrl: 'string'
95
69
  },
96
70
  derived: {
97
71
  listening: {
@@ -140,70 +114,60 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
140
114
  /**
141
115
  * Attach event listeners to a socket.
142
116
  * @param {Socket} socket - The socket to attach listeners to
143
- * @param {sessionId} sessionId - The socket related session ID
144
117
  * @returns {void}
145
118
  */
146
- _attachSocketEventListeners: function _attachSocketEventListeners(socket, sessionId) {
119
+ _attachSocketEventListeners: function _attachSocketEventListeners(socket) {
147
120
  var _this2 = this;
148
121
  socket.on('close', function (event) {
149
- return _this2._onclose(sessionId, event, socket);
122
+ return _this2._onclose(event, socket);
150
123
  });
151
124
  socket.on('message', function () {
152
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
153
- args[_key] = arguments[_key];
154
- }
155
- return _this2._onmessage.apply(_this2, [sessionId].concat(args));
125
+ return _this2._onmessage.apply(_this2, arguments);
156
126
  });
157
127
  socket.on('pong', function () {
158
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
159
- args[_key2] = arguments[_key2];
160
- }
161
- return _this2._setTimeOffset.apply(_this2, [sessionId].concat(args));
128
+ return _this2._setTimeOffset.apply(_this2, arguments);
162
129
  });
163
130
  socket.on('sequence-mismatch', function () {
164
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
165
- args[_key3] = arguments[_key3];
131
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
132
+ args[_key] = arguments[_key];
166
133
  }
167
- return _this2._emit.apply(_this2, [sessionId, 'sequence-mismatch'].concat(args));
134
+ return _this2._emit.apply(_this2, ['sequence-mismatch'].concat(args));
168
135
  });
169
136
  socket.on('ping-pong-latency', function () {
170
- for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
171
- args[_key4] = arguments[_key4];
137
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
138
+ args[_key2] = arguments[_key2];
172
139
  }
173
- return _this2._emit.apply(_this2, [sessionId, 'ping-pong-latency'].concat(args));
140
+ return _this2._emit.apply(_this2, ['ping-pong-latency'].concat(args));
174
141
  });
175
142
  },
176
143
  /**
177
144
  * Handle imminent shutdown by establishing a new connection while keeping
178
145
  * the current one alive (make-before-break).
179
146
  * Idempotent: will no-op if already in progress.
180
- * @param {string} sessionId - The session ID for which the shutdown is imminent
181
147
  * @returns {void}
182
148
  */
183
- _handleImminentShutdown: function _handleImminentShutdown(sessionId) {
149
+ _handleImminentShutdown: function _handleImminentShutdown() {
184
150
  var _this3 = this;
185
- var oldSocket = this.sockets.get(sessionId);
151
+ var oldSocket = this.socket;
186
152
  try {
187
- // Idempotent: if we already have a switchover backoff call for this session,
188
- // a switchover is in progress – do nothing.
189
- if (this._shutdownSwitchoverBackoffCalls.get(sessionId)) {
190
- this.logger.info("".concat(this.namespace, ": [shutdown] switchover already in progress for ").concat(sessionId));
153
+ if (this._shutdownSwitchoverBackoffCall) {
154
+ this.logger.info("".concat(this.namespace, ": [shutdown] switchover already in progress"));
191
155
  return;
192
156
  }
193
157
  this._shutdownSwitchoverId = "".concat((0, _now.default)());
194
- this.logger.info("".concat(this.namespace, ": [shutdown] switchover start, id=").concat(this._shutdownSwitchoverId, " for ").concat(sessionId));
195
- this._connectWithBackoff(undefined, sessionId, {
158
+ this.logger.info("".concat(this.namespace, ": [shutdown] switchover start, id=").concat(this._shutdownSwitchoverId));
159
+ this._connectWithBackoff(undefined, {
196
160
  isShutdownSwitchover: true,
197
161
  attemptOptions: {
198
162
  isShutdownSwitchover: true,
199
163
  onSuccess: function onSuccess(newSocket, webSocketUrl) {
200
- _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover connected, url: ").concat(webSocketUrl, " for ").concat(sessionId));
164
+ _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover connected, url: ").concat(webSocketUrl));
201
165
 
202
166
  // Atomically switch active socket reference
203
- _this3.socket = _this3.sockets.get(_this3.defaultSessionId);
204
- _this3.connected = _this3.hasConnectedSockets(); // remain connected throughout
167
+ _this3.socket = newSocket;
168
+ _this3.connected = true; // remain connected throughout
205
169
 
206
- _this3._emit(sessionId, 'event:mercury_shutdown_switchover_complete', {
170
+ _this3._emit('event:mercury_shutdown_switchover_complete', {
207
171
  url: webSocketUrl
208
172
  });
209
173
  if (oldSocket) {
@@ -212,18 +176,18 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
212
176
  }
213
177
  }
214
178
  }).then(function () {
215
- _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover completed successfully for ").concat(sessionId));
179
+ _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover completed successfully"));
216
180
  }).catch(function (err) {
217
- _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover exhausted retries; will fall back to normal reconnection for ").concat(sessionId, ": "), err);
218
- _this3._emit(sessionId, 'event:mercury_shutdown_switchover_failed', {
181
+ _this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover exhausted retries; will fall back to normal reconnection"), err);
182
+ _this3._emit('event:mercury_shutdown_switchover_failed', {
219
183
  reason: err
220
184
  });
221
185
  // Old socket will eventually close with 4001, triggering normal reconnection
222
186
  });
223
187
  } catch (e) {
224
- this.logger.error("".concat(this.namespace, ": [shutdown] error during switchover for ").concat(sessionId), e);
225
- this._shutdownSwitchoverBackoffCalls.delete(sessionId);
226
- this._emit(sessionId, 'event:mercury_shutdown_switchover_failed', {
188
+ this.logger.error("".concat(this.namespace, ": [shutdown] error during switchover"), e);
189
+ this._shutdownSwitchoverBackoffCall = undefined;
190
+ this._emit('event:mercury_shutdown_switchover_failed', {
227
191
  reason: e
228
192
  });
229
193
  }
@@ -236,153 +200,57 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
236
200
  return this.lastError;
237
201
  },
238
202
  /**
239
- * Get all active socket connections
240
- * @returns {Map} Map of sessionId to socket instances
241
- */
242
- getSockets: function getSockets() {
243
- return this.sockets;
244
- },
245
- /**
246
- * Get a specific socket by connection ID
247
- * @param {string} sessionId - The connection identifier
248
- * @returns {Socket|undefined} The socket instance or undefined if not found
203
+ * Get the underlying WebSocket.
204
+ * @returns {any} The socket instance, or undefined if not connected.
249
205
  */
250
206
  getSocket: function getSocket() {
251
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
252
- return this.sockets.get(sessionId);
207
+ return this.socket;
253
208
  },
254
- /**
255
- * Check if a socket is connected
256
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier
257
- * @returns {boolean|undefined} True if the socket is connected
258
- */
259
- hasConnectedSockets: function hasConnectedSockets() {
260
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
261
- var socket = this.sockets.get(sessionId || this.defaultSessionId);
262
- return socket === null || socket === void 0 ? void 0 : socket.connected;
263
- },
264
- /**
265
- * Check if any sockets are connecting
266
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier
267
- * @returns {boolean|undefined} True if the socket is connecting
268
- */
269
- hasConnectingSockets: function hasConnectingSockets() {
270
- var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
271
- var socket = this.sockets.get(sessionId || this.defaultSessionId);
272
- return socket === null || socket === void 0 ? void 0 : socket.connecting;
273
- },
274
- /**
275
- * Connect to Mercury for a specific session.
276
- * @param {string} [webSocketUrl] - Optional websocket URL override. Falls back to the device websocket URL.
277
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier for this connection.
278
- * @returns {Promise<void>} Resolves when connection flow completes for the session.
279
- */
280
209
  connect: function connect(webSocketUrl) {
281
210
  var _this4 = this;
282
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
283
- if (!this._connectPromises) this._connectPromises = new _map.default();
284
-
285
- // First check if there's already a connection promise for this session
286
- if (this._connectPromises.has(sessionId)) {
287
- this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already in progress, returning existing promise"));
288
- return this._connectPromises.get(sessionId);
289
- }
290
- var sessionSocket = this.sockets.get(sessionId);
291
- if (sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connected || sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connecting) {
292
- this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already connected, will not connect again"));
211
+ if (this.connected) {
212
+ this.logger.info("".concat(this.namespace, ": already connected, will not connect again"));
293
213
  return _promise.default.resolve();
294
214
  }
215
+
216
+ // If already connecting, return the existing promise so callers can await it
217
+ if (this._connectPromise) {
218
+ this.logger.info("".concat(this.namespace, ": connection already in progress, returning existing promise"));
219
+ return this._connectPromise;
220
+ }
295
221
  this.connecting = true;
296
- this.logger.info("".concat(this.namespace, ": starting connection attempt for ").concat(sessionId));
297
- this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
298
- var connectPromise = _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
299
- _this4.logger.info("".concat(_this4.namespace, ": connecting ").concat(sessionId));
300
- return _this4._connectWithBackoff(webSocketUrl, sessionId);
222
+ this.logger.info("".concat(this.namespace, ": starting connection attempt"));
223
+ this._connectPromise = _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
224
+ _this4.logger.info("".concat(_this4.namespace, ": connecting"));
225
+ return _this4._connectWithBackoff(webSocketUrl);
301
226
  }).finally(function () {
302
- _this4._connectPromises.delete(sessionId);
227
+ _this4._connectPromise = null;
303
228
  });
304
- this._connectPromises.set(sessionId, connectPromise);
305
- return connectPromise;
306
- },
307
- logout: function logout() {
308
- this.logger.info("".concat(this.namespace, ": logout() called"));
309
- this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
310
- return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
311
- code: 3050,
312
- reason: this.config.beforeLogoutOptionsCloseReason
313
- } : undefined);
229
+ return this._connectPromise;
314
230
  },
315
- /**
316
- * Disconnect a Mercury socket for a specific session.
317
- * @param {object} [options] - Optional websocket close options (for example: `{code, reason}`).
318
- * @param {string} [sessionId=this.defaultSessionId] - The session identifier to disconnect.
319
- * @returns {Promise<void>} Resolves after disconnect cleanup and close handling are initiated/completed.
320
- */
321
231
  disconnect: function disconnect(options) {
322
232
  var _this5 = this;
323
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
324
233
  this.logger.info("".concat(this.namespace, "#disconnect: connecting state: ").concat(this.connecting, ", connected state: ").concat(this.connected, ", socket exists: ").concat(!!this.socket, ", options: ").concat((0, _stringify.default)(options)));
325
234
  return new _promise.default(function (resolve) {
326
- var backoffCall = _this5.backoffCalls.get(sessionId);
327
- if (backoffCall) {
328
- _this5.logger.info("".concat(_this5.namespace, ": aborting connection ").concat(sessionId));
329
- backoffCall.abort();
330
- _this5.backoffCalls.delete(sessionId);
331
- }
332
- var shutdownSwitchoverBackoffCall = _this5._shutdownSwitchoverBackoffCalls.get(sessionId);
333
- if (shutdownSwitchoverBackoffCall) {
334
- _this5.logger.info("".concat(_this5.namespace, ": aborting shutdown switchover connection ").concat(sessionId));
335
- shutdownSwitchoverBackoffCall.abort();
336
- _this5._shutdownSwitchoverBackoffCalls.delete(sessionId);
337
- }
338
- // Clean up any pending connection promises
339
- if (_this5._connectPromises) {
340
- _this5._connectPromises.delete(sessionId);
341
- }
342
- var sessionSocket = _this5.sockets.get(sessionId);
343
- var suffix = sessionId === _this5.defaultSessionId ? '' : ":".concat(sessionId);
344
- if (sessionSocket) {
345
- sessionSocket.removeAllListeners('message');
346
- sessionSocket.connecting = false;
347
- sessionSocket.connected = false;
348
- _this5.once(sessionId === _this5.defaultSessionId ? 'offline' : "offline".concat(suffix), resolve);
349
- resolve(sessionSocket.close(options || undefined));
235
+ if (_this5.backoffCall) {
236
+ _this5.logger.info("".concat(_this5.namespace, ": aborting connection"));
237
+ _this5.backoffCall.abort();
238
+ }
239
+ if (_this5._shutdownSwitchoverBackoffCall) {
240
+ _this5.logger.info("".concat(_this5.namespace, ": aborting shutdown switchover"));
241
+ _this5._shutdownSwitchoverBackoffCall.abort();
242
+ }
243
+ if (_this5.socket) {
244
+ _this5.socket.removeAllListeners('message');
245
+ _this5.once('offline', function () {
246
+ _this5._emit('disconnected');
247
+ resolve();
248
+ });
249
+ _this5.socket.close(options);
250
+ return;
350
251
  }
252
+ _this5._emit('disconnected');
351
253
  resolve();
352
-
353
- // Update overall connected status
354
- _this5.connected = _this5.hasConnectedSockets();
355
- });
356
- },
357
- /**
358
- * Disconnect all socket connections
359
- * @param {object} options - Close options
360
- * @returns {Promise} Promise that resolves when all connections are closed
361
- */
362
- disconnectAll: function disconnectAll(options) {
363
- var _this6 = this;
364
- var disconnectPromises = [];
365
- var _iterator = _createForOfIteratorHelper(this.sockets.keys()),
366
- _step;
367
- try {
368
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
369
- var sessionId = _step.value;
370
- disconnectPromises.push(this.disconnect(options, sessionId));
371
- }
372
- } catch (err) {
373
- _iterator.e(err);
374
- } finally {
375
- _iterator.f();
376
- }
377
- return _promise.default.all(disconnectPromises).then(function () {
378
- _this6.connected = false;
379
- _this6.sockets.clear();
380
- _this6.sessionWebSocketUrls.clear();
381
- _this6.backoffCalls.clear();
382
- // Clear connection promises to prevent stale promises
383
- if (_this6._connectPromises) {
384
- _this6._connectPromises.clear();
385
- }
386
254
  });
387
255
  },
388
256
  listen: function listen() {
@@ -406,7 +274,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
406
274
  });
407
275
  },
408
276
  _prepareUrl: function _prepareUrl(webSocketUrl) {
409
- var _this7 = this;
277
+ var _this6 = this;
410
278
  if (!webSocketUrl) {
411
279
  webSocketUrl = this.webex.internal.device.webSocketUrl;
412
280
  }
@@ -414,16 +282,16 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
414
282
  if (haMessagingEnabled) {
415
283
  var highPrioritySocketUrl;
416
284
  try {
417
- highPrioritySocketUrl = _this7.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
285
+ highPrioritySocketUrl = _this6.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
418
286
  } catch (e) {
419
- _this7.logger.warn("".concat(_this7.namespace, ": error converting to high priority url"), e);
287
+ _this6.logger.warn("".concat(_this6.namespace, ": error converting to high priority url"), e);
420
288
  }
421
289
  if (!highPrioritySocketUrl) {
422
290
  var _url$parse;
423
291
  var hostFromUrl = (_url$parse = _url.default.parse(webSocketUrl, true)) === null || _url$parse === void 0 ? void 0 : _url$parse.host;
424
- var isValidHost = _this7.webex.internal.services.isValidHost(hostFromUrl);
292
+ var isValidHost = _this6.webex.internal.services.isValidHost(hostFromUrl);
425
293
  if (!isValidHost) {
426
- _this7.logger.error("".concat(_this7.namespace, ": host ").concat(hostFromUrl, " is not a valid host from host catalog"));
294
+ _this6.logger.error("".concat(_this6.namespace, ": host ").concat(hostFromUrl, " is not a valid host from host catalog"));
427
295
  return '';
428
296
  }
429
297
  }
@@ -433,7 +301,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
433
301
  }).then(function (wsUrl) {
434
302
  webSocketUrl = wsUrl;
435
303
  }).then(function () {
436
- return _this7.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
304
+ return _this6.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
437
305
  }).then(function (webSharedMercury) {
438
306
  if (!webSocketUrl) {
439
307
  return '';
@@ -451,7 +319,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
451
319
  });
452
320
  (0, _deleteProperty.default)(webSocketUrl.query, 'bufferStates');
453
321
  }
454
- if ((0, _lodash.get)(_this7, 'webex.config.device.ephemeral', false)) {
322
+ if ((0, _lodash.get)(_this6, 'webex.config.device.ephemeral', false)) {
455
323
  webSocketUrl.query.multipleConnections = true;
456
324
  }
457
325
  webSocketUrl.query.clientTimestamp = (0, _now.default)();
@@ -459,23 +327,20 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
459
327
  return _url.default.format(webSocketUrl);
460
328
  });
461
329
  },
462
- _attemptConnection: function _attemptConnection(socketUrl, sessionId, callback) {
463
- var _this8 = this;
464
- var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
330
+ _attemptConnection: function _attemptConnection(socketUrl, callback) {
331
+ var _this7 = this;
332
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
465
333
  var _options$isShutdownSw = options.isShutdownSwitchover,
466
334
  isShutdownSwitchover = _options$isShutdownSw === void 0 ? false : _options$isShutdownSw,
467
335
  _options$onSuccess = options.onSuccess,
468
336
  onSuccess = _options$onSuccess === void 0 ? null : _options$onSuccess;
469
337
  var socket = new _socket.default();
470
- socket.connecting = true;
471
338
  var newWSUrl;
472
- this._attachSocketEventListeners(socket, sessionId);
473
- var backoffCall = isShutdownSwitchover ? this._shutdownSwitchoverBackoffCalls.get(sessionId) : this.backoffCalls.get(sessionId);
339
+ this._attachSocketEventListeners(socket);
474
340
 
475
341
  // Check appropriate backoff call based on connection type
476
- if (!backoffCall) {
477
- var mode = isShutdownSwitchover ? 'switchover backoff call' : 'backoffCall';
478
- var msg = "".concat(this.namespace, ": prevent socket open when ").concat(mode, " no longer defined for ").concat(sessionId);
342
+ if (isShutdownSwitchover && !this._shutdownSwitchoverBackoffCall) {
343
+ var msg = "".concat(this.namespace, ": prevent socket open when switchover backoff call no longer defined");
479
344
  var err = new Error(msg);
480
345
  this.logger.info(msg);
481
346
 
@@ -483,15 +348,26 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
483
348
  callback(err);
484
349
  return _promise.default.reject(err);
485
350
  }
351
+ if (!isShutdownSwitchover && !this.backoffCall) {
352
+ var _msg = "".concat(this.namespace, ": prevent socket open when backoffCall no longer defined");
353
+ var _err = new Error(_msg);
354
+ this.logger.info(_msg);
355
+
356
+ // Call the callback with the error before rejecting
357
+ callback(_err);
358
+
359
+ // eslint-disable-next-line no-unreachable
360
+ return _promise.default.reject(_err);
361
+ }
486
362
 
487
363
  // For shutdown switchover, don't set socket yet (make-before-break)
488
364
  // For normal connection, set socket before opening to allow disconnect() to close it
489
365
  if (!isShutdownSwitchover) {
490
- this.sockets.set(sessionId, socket);
366
+ this.socket = socket;
491
367
  }
492
- return this._prepareAndOpenSocket(socket, socketUrl, sessionId, isShutdownSwitchover).then(function (webSocketUrl) {
368
+ return this._prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover).then(function (webSocketUrl) {
493
369
  newWSUrl = webSocketUrl;
494
- _this8.logger.info("".concat(_this8.namespace, ": ").concat(isShutdownSwitchover ? '[shutdown] switchover' : '', " connected to mercury, success, action: connected for ").concat(sessionId, ", url: ").concat(newWSUrl));
370
+ _this7.logger.info("".concat(_this7.namespace, ": ").concat(isShutdownSwitchover ? '[shutdown] switchover' : '', " connected to mercury, success, action: connected, url: ").concat(newWSUrl));
495
371
 
496
372
  // Custom success handler for shutdown switchover
497
373
  if (onSuccess) {
@@ -502,46 +378,46 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
502
378
 
503
379
  // Default behavior for normal connection
504
380
  callback();
505
- return _this8.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
381
+ return _this7.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
506
382
  if (haMessagingEnabled) {
507
- return _this8.webex.internal.device.refresh();
383
+ return _this7.webex.internal.device.refresh();
508
384
  }
509
385
  return _promise.default.resolve();
510
386
  });
511
387
  }).catch(function (reason) {
388
+ var _this7$backoffCall, _this7$backoffCall3;
512
389
  // For shutdown, simpler error handling - just callback for retry
513
390
  if (isShutdownSwitchover) {
514
- _this8.logger.info("".concat(_this8.namespace, ": [shutdown] switchover attempt failed for ").concat(sessionId), reason);
391
+ _this7.logger.info("".concat(_this7.namespace, ": [shutdown] switchover attempt failed"), reason);
515
392
  return callback(reason);
516
393
  }
517
394
 
518
395
  // Normal connection error handling (existing complex logic)
519
- _this8.lastError = reason; // remember the last error
396
+ _this7.lastError = reason; // remember the last error
520
397
 
521
- var backoffCallNormal = _this8.backoffCalls.get(sessionId);
522
398
  // Suppress connection errors that appear to be network related. This
523
399
  // may end up suppressing metrics during outages, but we might not care
524
400
  // (especially since many of our outages happen in a way that client
525
401
  // metrics can't be trusted).
526
- if (reason.code !== 1006 && backoffCallNormal && (backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()) > 0) {
527
- _this8._emit(sessionId, 'connection_failed', reason, {
528
- sessionId: sessionId,
529
- retries: backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()
402
+ if (reason.code !== 1006 && _this7.backoffCall && ((_this7$backoffCall = _this7.backoffCall) === null || _this7$backoffCall === void 0 ? void 0 : _this7$backoffCall.getNumRetries()) > 0) {
403
+ var _this7$backoffCall2;
404
+ _this7._emit('connection_failed', reason, {
405
+ retries: (_this7$backoffCall2 = _this7.backoffCall) === null || _this7$backoffCall2 === void 0 ? void 0 : _this7$backoffCall2.getNumRetries()
530
406
  });
531
407
  }
532
- _this8.logger.info("".concat(_this8.namespace, ": connection attempt failed for ").concat(sessionId), reason, (backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.getNumRetries()) === 0 ? reason.stack : '');
408
+ _this7.logger.info("".concat(_this7.namespace, ": connection attempt failed"), reason, ((_this7$backoffCall3 = _this7.backoffCall) === null || _this7$backoffCall3 === void 0 ? void 0 : _this7$backoffCall3.getNumRetries()) === 0 ? reason.stack : '');
533
409
  // UnknownResponse is produced by IE for any 4XXX; treated it like a bad
534
410
  // web socket url and let WDM handle the token checking
535
411
  if (reason instanceof _errors.UnknownResponse) {
536
- _this8.logger.info("".concat(_this8.namespace, ": received unknown response code for ").concat(sessionId, ", refreshing device registration"));
537
- return _this8.webex.internal.device.refresh().then(function () {
412
+ _this7.logger.info("".concat(_this7.namespace, ": received unknown response code, refreshing device registration"));
413
+ return _this7.webex.internal.device.refresh().then(function () {
538
414
  return callback(reason);
539
415
  });
540
416
  }
541
417
  // NotAuthorized implies expired token
542
418
  if (reason instanceof _errors.NotAuthorized) {
543
- _this8.logger.info("".concat(_this8.namespace, ": received authorization error for ").concat(sessionId, ", reauthorizing"));
544
- return _this8.webex.credentials.refresh({
419
+ _this7.logger.info("".concat(_this7.namespace, ": received authorization error, reauthorizing"));
420
+ return _this7.webex.credentials.refresh({
545
421
  force: true
546
422
  }).then(function () {
547
423
  return callback(reason);
@@ -556,20 +432,20 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
556
432
  // BadRequest implies current credentials are for a Service Account
557
433
  // Forbidden implies current user is not entitle for Webex
558
434
  if (reason instanceof _errors.BadRequest || reason instanceof _errors.Forbidden) {
559
- _this8.logger.warn("".concat(_this8.namespace, ": received unrecoverable response from mercury for ").concat(sessionId));
560
- backoffCallNormal === null || backoffCallNormal === void 0 ? void 0 : backoffCallNormal.abort();
435
+ _this7.logger.warn("".concat(_this7.namespace, ": received unrecoverable response from mercury"));
436
+ _this7.backoffCall.abort();
561
437
  return callback(reason);
562
438
  }
563
439
  if (reason instanceof _errors.ConnectionError) {
564
- return _this8.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
440
+ return _this7.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
565
441
  var wsUrl = newWSUrl || reason.webSocketUrl;
566
442
  if (haMessagingEnabled) {
567
- _this8.logger.info("".concat(_this8.namespace, ": received a generic connection error for ").concat(sessionId, ", will try to connect to another datacenter. failed, action: 'failed', url: ").concat(wsUrl, " error: ").concat(reason.message));
443
+ _this7.logger.info("".concat(_this7.namespace, ": received a generic connection error, will try to connect to another datacenter. failed, action: 'failed', url: ").concat(wsUrl, " error: ").concat(reason.message));
568
444
  if (wsUrl) {
569
- _this8.logger.info("".concat(_this8.namespace, ": marking ").concat(wsUrl, " as failed for ").concat(sessionId, " due to connection error"));
570
- return _this8.webex.internal.services.markFailedUrl(wsUrl);
445
+ _this7.logger.info("".concat(_this7.namespace, ": marking ").concat(wsUrl, " as failed due to connection error"));
446
+ return _this7.webex.internal.services.markFailedUrl(wsUrl);
571
447
  }
572
- _this8.logger.info("".concat(_this8.namespace, ": no socket url available to mark as failed for ").concat(sessionId, " due to connection error"));
448
+ _this7.logger.info("".concat(_this7.namespace, ": no socket url available to mark as failed due to connection error"));
573
449
  }
574
450
  return null;
575
451
  }).then(function () {
@@ -578,45 +454,39 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
578
454
  }
579
455
  return callback(reason);
580
456
  }).catch(function (reason) {
581
- _this8.logger.error("".concat(_this8.namespace, ": failed to handle connection failure for ").concat(sessionId), reason);
457
+ _this7.logger.error("".concat(_this7.namespace, ": failed to handle connection failure"), reason);
582
458
  callback(reason);
583
459
  });
584
460
  },
585
- _prepareAndOpenSocket: function _prepareAndOpenSocket(socket, socketUrl, sessionId) {
586
- var _this9 = this;
587
- var isShutdownSwitchover = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
461
+ _prepareAndOpenSocket: function _prepareAndOpenSocket(socket, socketUrl) {
462
+ var _this8 = this;
463
+ var isShutdownSwitchover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
588
464
  var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
589
465
  return _promise.default.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
590
466
  var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
591
467
  webSocketUrl = _ref2[0],
592
468
  token = _ref2[1];
593
469
  var options = {
594
- forceCloseDelay: _this9.config.forceCloseDelay,
595
- pingInterval: _this9.config.pingInterval,
596
- pongTimeout: _this9.config.pongTimeout,
470
+ forceCloseDelay: _this8.config.forceCloseDelay,
471
+ pingInterval: _this8.config.pingInterval,
472
+ pongTimeout: _this8.config.pongTimeout,
597
473
  token: token.toString(),
598
- trackingId: "".concat(_this9.webex.sessionId, "_").concat((0, _now.default)()),
599
- logger: _this9.logger
474
+ trackingId: "".concat(_this8.webex.sessionId, "_").concat((0, _now.default)()),
475
+ logger: _this8.logger
600
476
  };
601
- if (_this9.webex.config.defaultMercuryOptions) {
477
+ if (_this8.webex.config.defaultMercuryOptions) {
602
478
  var customOptionsMsg = isShutdownSwitchover ? 'setting custom options for switchover' : 'setting custom options';
603
- _this9.logger.info("".concat(_this9.namespace, ": ").concat(customOptionsMsg));
604
- options = _objectSpread(_objectSpread({}, options), _this9.webex.config.defaultMercuryOptions);
479
+ _this8.logger.info("".concat(_this8.namespace, ": ").concat(customOptionsMsg));
480
+ options = _objectSpread(_objectSpread({}, options), _this8.webex.config.defaultMercuryOptions);
605
481
  }
482
+ _this8.logger.info("".concat(_this8.namespace, ": ").concat(logPrefix, " url: ").concat(webSocketUrl));
606
483
 
607
- // Set the socket before opening it. This allows a disconnect() to close
608
- // the socket if it is in the process of being opened.
609
- _this9.sockets.set(sessionId, socket);
610
- _this9.socket = _this9.sockets.get(_this9.defaultSessionId);
611
- _this9.logger.info("".concat(_this9.namespace, " ").concat(logPrefix, " url for ").concat(sessionId, ": ").concat(webSocketUrl));
612
-
613
- // Remember the resolved URL used to open this socket so that
614
- // reconnection in _onclose re-derives from a catalog-valid host. This is
615
- // captured before socket.open(), which a lower layer (e.g. the same-site
616
- // websocket proxy done with interceptors) may rewrite into a non-catalog host.
617
- // Reusing the post-proxy native socket URL would fail
618
- // host-catalog validation in _prepareUrl and block reconnection.
619
- _this9.sessionWebSocketUrls.set(sessionId, webSocketUrl);
484
+ // Store the resolved URL before socket.open(), which may be rewritten by
485
+ // an interceptor (e.g. same-site websocket proxy). On reconnection we need
486
+ // the original catalog-valid URL, not the post-proxy one from socket.url.
487
+ if (!isShutdownSwitchover) {
488
+ _this8.resolvedWebSocketUrl = webSocketUrl;
489
+ }
620
490
  return socket.open(webSocketUrl, options).then(function () {
621
491
  return webSocketUrl;
622
492
  }).catch(function (err) {
@@ -625,126 +495,93 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
625
495
  });
626
496
  });
627
497
  },
628
- _connectWithBackoff: function _connectWithBackoff(webSocketUrl, sessionId) {
629
- var _this0 = this;
630
- var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
498
+ _connectWithBackoff: function _connectWithBackoff(webSocketUrl) {
499
+ var _this9 = this;
500
+ var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
631
501
  var _context$isShutdownSw = context.isShutdownSwitchover,
632
502
  isShutdownSwitchover = _context$isShutdownSw === void 0 ? false : _context$isShutdownSw,
633
503
  _context$attemptOptio = context.attemptOptions,
634
504
  attemptOptions = _context$attemptOptio === void 0 ? {} : _context$attemptOptio;
635
505
  return new _promise.default(function (resolve, reject) {
636
- // eslint gets confused about whether call is actually used
506
+ // eslint gets confused about whether or not call is actually used
637
507
  // eslint-disable-next-line prefer-const
638
508
  var call;
639
509
  var onComplete = function onComplete(err) {
640
- var sid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : sessionId;
510
+ // Clear state flags based on connection type
641
511
  if (isShutdownSwitchover) {
642
- _this0._shutdownSwitchoverBackoffCalls.delete(sid);
512
+ _this9._shutdownSwitchoverBackoffCall = undefined;
643
513
  } else {
644
- _this0.backoffCalls.delete(sid);
514
+ _this9.connecting = false;
515
+ _this9.backoffCall = undefined;
645
516
  }
646
- var sessionSocket = _this0.sockets.get(sid);
647
517
  if (err) {
648
518
  var msg = isShutdownSwitchover ? "[shutdown] switchover failed after ".concat(call.getNumRetries(), " retries") : "failed to connect after ".concat(call.getNumRetries(), " retries");
649
- _this0.logger.info("".concat(_this0.namespace, ": ").concat(msg, "; log statement about next retry was inaccurate; ").concat(err));
650
- if (sessionSocket) {
651
- sessionSocket.connecting = false;
652
- sessionSocket.connected = false;
653
- }
519
+ _this9.logger.info("".concat(_this9.namespace, ": ").concat(msg, "; log statement about next retry was inaccurate; ").concat(err));
654
520
  return reject(err);
655
521
  }
656
522
 
657
- // Update overall connected status
658
- if (sessionSocket) {
659
- sessionSocket.connecting = false;
660
- sessionSocket.connected = true;
661
- }
662
523
  // Default success handling for normal connections
663
524
  if (!isShutdownSwitchover) {
664
- _this0.connecting = _this0.hasConnectingSockets();
665
- _this0.connected = _this0.hasConnectedSockets();
666
- _this0.hasEverConnected = true;
667
- _this0._emit(sid, 'online');
668
- if (_this0.connected) {
669
- _this0.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
670
- }
525
+ _this9.connected = true;
526
+ _this9.hasEverConnected = true;
527
+ _this9._emit('online');
528
+ _this9.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
671
529
  }
672
530
  return resolve();
673
531
  };
532
+
674
533
  // eslint-disable-next-line prefer-reflect
675
534
  call = _backoff.default.call(function (callback) {
676
535
  var attemptNum = call.getNumRetries();
677
536
  var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
678
- _this0.logger.info("".concat(_this0.namespace, ": executing ").concat(logPrefix, " attempt ").concat(attemptNum, " for ").concat(sessionId));
679
- _this0._attemptConnection(webSocketUrl, sessionId, callback, attemptOptions);
680
- }, function (err) {
681
- return onComplete(err, sessionId);
682
- });
537
+ _this9.logger.info("".concat(_this9.namespace, ": executing ").concat(logPrefix, " attempt ").concat(attemptNum));
538
+ _this9._attemptConnection(webSocketUrl, callback, attemptOptions);
539
+ }, onComplete);
683
540
  call.setStrategy(new _backoff.default.ExponentialStrategy({
684
- initialDelay: _this0.config.backoffTimeReset,
685
- maxDelay: _this0.config.backoffTimeMax
541
+ initialDelay: _this9.config.backoffTimeReset,
542
+ maxDelay: _this9.config.backoffTimeMax
686
543
  }));
687
- if (_this0.config.initialConnectionMaxRetries && !_this0.hasEverConnected && !isShutdownSwitchover) {
688
- call.failAfter(_this0.config.initialConnectionMaxRetries);
689
- } else if (_this0.config.maxRetries) {
690
- call.failAfter(_this0.config.maxRetries);
691
- }
692
-
693
- // Store the call BEFORE setting up event handlers to prevent race conditions
694
- // Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
695
- if (isShutdownSwitchover) {
696
- _this0._shutdownSwitchoverBackoffCalls.set(sessionId, call);
697
- } else {
698
- _this0.backoffCalls.set(sessionId, call);
544
+ if (_this9.config.initialConnectionMaxRetries && !_this9.hasEverConnected && !isShutdownSwitchover) {
545
+ call.failAfter(_this9.config.initialConnectionMaxRetries);
546
+ } else if (_this9.config.maxRetries) {
547
+ call.failAfter(_this9.config.maxRetries);
699
548
  }
700
549
  call.on('abort', function () {
701
550
  var msg = isShutdownSwitchover ? 'Shutdown Switchover' : 'Connection';
702
- _this0.logger.info("".concat(_this0.namespace, ": ").concat(msg, " aborted for ").concat(sessionId));
703
- reject(new Error("Mercury ".concat(msg, " Aborted for ").concat(sessionId)));
551
+ _this9.logger.info("".concat(_this9.namespace, ": ").concat(msg, " aborted"));
552
+ reject(new Error("Mercury ".concat(msg, " Aborted")));
704
553
  });
705
554
  call.on('callback', function (err) {
706
555
  if (err) {
707
556
  var number = call.getNumRetries();
708
- var delay = Math.min(call.strategy_.nextBackoffDelay_, _this0.config.backoffTimeMax);
557
+ var delay = Math.min(call.strategy_.nextBackoffDelay_, _this9.config.backoffTimeMax);
709
558
  var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : '';
710
- _this0.logger.info("".concat(_this0.namespace, ": ").concat(logPrefix, " failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms for ").concat(sessionId));
559
+ _this9.logger.info("".concat(_this9.namespace, ": ").concat(logPrefix, " failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
711
560
  /* istanbul ignore if */
712
561
  if (process.env.NODE_ENV === 'development') {
713
- _this0.logger.debug("".concat(_this0.namespace, ": "), err, err.stack);
562
+ _this9.logger.debug("".concat(_this9.namespace, ": "), err, err.stack);
714
563
  }
715
564
  return;
716
565
  }
717
- _this0.logger.info("".concat(_this0.namespace, ": connected ").concat(sessionId));
566
+ _this9.logger.info("".concat(_this9.namespace, ": connected"));
718
567
  });
568
+
569
+ // Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
570
+ if (isShutdownSwitchover) {
571
+ _this9._shutdownSwitchoverBackoffCall = call;
572
+ } else {
573
+ _this9.backoffCall = call;
574
+ }
719
575
  call.start();
720
576
  });
721
577
  },
722
578
  _emit: function _emit() {
723
- for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
724
- args[_key5] = arguments[_key5];
579
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
580
+ args[_key3] = arguments[_key3];
725
581
  }
726
582
  try {
727
- if (!args || args.length === 0) {
728
- return;
729
- }
730
-
731
- // New signature: _emit(sessionId, eventName, ...rest)
732
- // Backwards compatibility: if the first arg isn't a known sessionId (or defaultSessionId),
733
- // treat the call as the old signature and forward directly to trigger(...)
734
- var first = args[0],
735
- second = args[1],
736
- rest = _arrayLikeToArray(args).slice(2);
737
- if (typeof first === 'string' && typeof second === 'string') {
738
- var sessionId = first;
739
- var eventName = second;
740
- var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
741
- this.trigger.apply(this, ["".concat(eventName).concat(suffix)].concat((0, _toConsumableArray2.default)(rest)));
742
- } else {
743
- // Old usage: _emit(eventName, ...args)
744
- this.trigger.apply(this, args);
745
- }
583
+ this.trigger.apply(this, args);
746
584
  } catch (error) {
747
- // Safely handle errors without causing additional issues during cleanup
748
585
  try {
749
586
  this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
750
587
  } catch (logError) {
@@ -775,7 +612,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
775
612
  }
776
613
  return handlers;
777
614
  },
778
- _submitMercuryClose4000Metric: function _submitMercuryClose4000Metric(sessionId, event, options) {
615
+ _submitMercuryClose4000Metric: function _submitMercuryClose4000Metric(event, options) {
779
616
  var action = options.action,
780
617
  isActiveSocket = options.isActiveSocket,
781
618
  messageType = options.messageType;
@@ -786,8 +623,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
786
623
  close_code: event.code,
787
624
  close_reason: event.reason || '',
788
625
  is_active_socket: isActiveSocket,
789
- message_type: messageType,
790
- session_id: sessionId
626
+ message_type: messageType
791
627
  },
792
628
  tags: {
793
629
  action: action,
@@ -798,40 +634,29 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
798
634
  this.logger.warn("".concat(this.namespace, ": failed to submit Mercury 4000 close metric"), error);
799
635
  }
800
636
  },
801
- _onclose: function _onclose(sessionId, event, sourceSocket) {
637
+ _onclose: function _onclose(event, sourceSocket) {
802
638
  // I don't see any way to avoid the complexity or statement count in here.
803
639
  /* eslint complexity: [0] */
804
640
 
805
641
  try {
642
+ var isActiveSocket = sourceSocket === this.socket;
806
643
  var reason = event.reason && event.reason.toLowerCase();
807
- var sessionSocket = this.sockets.get(sessionId);
808
- event.sessionId = sessionId;
809
- var isActiveSocket = sourceSocket === sessionSocket;
810
- // Reconnect using the resolved URL this session's socket was
811
- // opened with, captured in _prepareAndOpenSocket. Do NOT reuse
812
- // sourceSocket.url: that reflects the URL the native WebSocket was
813
- // actually opened with, which a lower layer may have rewritten
814
- // (e.g. via interceptors) into a host that is not in the SDK host
815
- // catalog. Feeding such a URL back into _prepareUrl fails host-catalog
816
- // validation and permanently blocks reconnection.
817
- var socketUrl = this.sessionWebSocketUrls.get(sessionId);
818
- this.sockets.delete(sessionId);
644
+
645
+ // Use the stored resolved URL for reconnection instead of sourceSocket.url,
646
+ // which may have been rewritten by an interceptor to a non-catalog host.
647
+ var socketUrl = this.resolvedWebSocketUrl || sourceSocket && sourceSocket.url;
819
648
  if (isActiveSocket) {
820
649
  // Only tear down state if the currently active socket closed
821
- if (sessionSocket) {
822
- sessionSocket.removeAllListeners();
823
- if (sessionId === this.defaultSessionId) this.unset('socket');
824
- this._emit(sessionId, 'offline', event);
825
- }
826
- // Update overall connected status
827
- this.connecting = this.hasConnectingSockets();
828
- this.connected = this.hasConnectedSockets();
829
- if (!this.connected) {
830
- this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
650
+ if (this.socket) {
651
+ this.socket.removeAllListeners();
831
652
  }
653
+ this.unset('socket');
654
+ this.connected = false;
655
+ this._emit('offline', event);
656
+ this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
832
657
  } else {
833
658
  // Old socket closed; do not flip connection state
834
- this.logger.info("".concat(this.namespace, ": [shutdown] non-active socket closed, code=").concat(event.code, " for ").concat(sessionId));
659
+ this.logger.info("".concat(this.namespace, ": [shutdown] non-active socket closed, code=").concat(event.code));
835
660
  // Clean up listeners from old socket now that it's closed
836
661
  if (sourceSocket) {
837
662
  sourceSocket.removeAllListeners();
@@ -840,29 +665,29 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
840
665
  switch (event.code) {
841
666
  case 1003:
842
667
  // metric: disconnect
843
- this.logger.info("".concat(this.namespace, ": Mercury service rejected last message for ").concat(sessionId, "; will not reconnect: ").concat(event.reason));
844
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
668
+ this.logger.info("".concat(this.namespace, ": Mercury service rejected last message; will not reconnect: ").concat(event.reason));
669
+ if (isActiveSocket) this._emit('offline.permanent', event);
845
670
  break;
846
671
  case 4000:
847
- // metric: disconnect
672
+ // metric: disconnect, check reason
848
673
  if (reason === 'replaced') {
849
- this._submitMercuryClose4000Metric(sessionId, event, {
674
+ this._submitMercuryClose4000Metric(event, {
850
675
  action: 'no_action',
851
676
  isActiveSocket: isActiveSocket,
852
677
  messageType: 'replaced'
853
678
  });
854
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " replaced; will not reconnect"));
855
- if (isActiveSocket) this._emit(sessionId, 'offline.replaced', event);
679
+ this.logger.info("".concat(this.namespace, ": socket replaced; will not reconnect"));
680
+ if (isActiveSocket) this._emit('offline.replaced', event);
856
681
  } else {
857
- this._submitMercuryClose4000Metric(sessionId, event, {
682
+ this._submitMercuryClose4000Metric(event, {
858
683
  action: isActiveSocket ? 'reconnect' : 'ignore_non_active',
859
684
  isActiveSocket: isActiveSocket,
860
685
  messageType: 'other'
861
686
  });
862
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected with 4000: ").concat(event.reason, "; reconnecting"));
687
+ this.logger.info("".concat(this.namespace, ": socket disconnected with 4000: ").concat(event.reason, "; reconnecting"));
863
688
  if (isActiveSocket) {
864
- this._emit(sessionId, 'offline.transient', event);
865
- this._reconnect(socketUrl, sessionId);
689
+ this._emit('offline.transient', event);
690
+ this._reconnect(socketUrl);
866
691
  }
867
692
  }
868
693
  break;
@@ -872,23 +697,23 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
872
697
  // Server closed active socket with 4001, meaning it expected this connection
873
698
  // to be replaced, but the switchover in _handleImminentShutdown failed.
874
699
  // This is a permanent failure - do not reconnect.
875
- this.logger.warn("".concat(this.namespace, ": active socket closed with 4001; shutdown switchover failed for ").concat(sessionId));
876
- this._emit(sessionId, 'offline.permanent', event);
700
+ this.logger.warn("".concat(this.namespace, ": active socket closed with 4001; shutdown switchover failed"));
701
+ this._emit('offline.permanent', event);
877
702
  } else {
878
703
  // Expected: old socket closed after successful switchover
879
- this.logger.info("".concat(this.namespace, ": old socket closed with 4001 (replaced during shutdown); no reconnect needed for ").concat(sessionId));
880
- this._emit(sessionId, 'offline.replaced', event);
704
+ this.logger.info("".concat(this.namespace, ": old socket closed with 4001 (replaced during shutdown); no reconnect needed"));
705
+ this._emit('offline.replaced', event);
881
706
  }
882
707
  break;
883
708
  case 1001:
884
709
  case 1005:
885
710
  case 1006:
886
711
  case 1011:
887
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
712
+ this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
888
713
  if (isActiveSocket) {
889
- this._emit(sessionId, 'offline.transient', event);
890
- this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting active socket to recover for ").concat(sessionId));
891
- this._reconnect(socketUrl, sessionId);
714
+ this._emit('offline.transient', event);
715
+ this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting active socket to recover"));
716
+ this._reconnect(socketUrl);
892
717
  }
893
718
  // metric: disconnect
894
719
  // if (code == 1011 && reason !== ping error) metric: unexpected disconnect
@@ -897,88 +722,85 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
897
722
  case 3050:
898
723
  // 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
899
724
  if (normalReconnectReasons.includes(reason)) {
900
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
725
+ this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
901
726
  if (isActiveSocket) {
902
- this._emit(sessionId, 'offline.transient', event);
903
- this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting due to normal close for ").concat(sessionId));
904
- this._reconnect(socketUrl, sessionId);
727
+ this._emit('offline.transient', event);
728
+ this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting due to normal close"));
729
+ this._reconnect(socketUrl);
905
730
  }
906
731
  // metric: disconnect
907
732
  // if (reason === done forced) metric: force closure
908
733
  } else {
909
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; will not reconnect: ").concat(event.reason));
910
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
734
+ this.logger.info("".concat(this.namespace, ": socket disconnected; will not reconnect: ").concat(event.reason));
735
+ if (isActiveSocket) this._emit('offline.permanent', event);
911
736
  }
912
737
  break;
913
738
  default:
914
- this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected unexpectedly; will not reconnect"));
739
+ this.logger.info("".concat(this.namespace, ": socket disconnected unexpectedly; will not reconnect"));
915
740
  // unexpected disconnect
916
- if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
741
+ if (isActiveSocket) this._emit('offline.permanent', event);
917
742
  }
918
743
  } catch (error) {
919
- this.logger.error("".concat(this.namespace, ": error occurred in close handler for ").concat(sessionId), error);
744
+ this.logger.error("".concat(this.namespace, ": error occurred in close handler"), error);
920
745
  }
921
746
  },
922
- _onmessage: function _onmessage(sessionId, event) {
923
- var _this1 = this;
924
- this._setTimeOffset(sessionId, event);
747
+ _onmessage: function _onmessage(event) {
748
+ var _this0 = this;
749
+ this._setTimeOffset(event);
925
750
  var envelope = event.data;
926
751
  if (process.env.ENABLE_MERCURY_LOGGING) {
927
- this.logger.debug("".concat(this.namespace, ": message envelope from ").concat(sessionId, ": "), envelope);
752
+ this.logger.debug("".concat(this.namespace, ": message envelope: "), envelope);
928
753
  }
929
- envelope.sessionId = sessionId;
930
754
 
931
755
  // Handle shutdown message shape: { type: 'shutdown' }
932
756
  if (envelope && envelope.type === 'shutdown') {
933
- this.logger.info("".concat(this.namespace, ": [shutdown] imminent shutdown message received for ").concat(sessionId));
934
- this._emit(sessionId, 'event:mercury_shutdown_imminent', envelope);
935
- this._handleImminentShutdown(sessionId);
757
+ this.logger.info("".concat(this.namespace, ": [shutdown] imminent shutdown message received"));
758
+ this._emit('event:mercury_shutdown_imminent', envelope);
759
+ this._handleImminentShutdown();
936
760
  return _promise.default.resolve();
937
761
  }
938
- envelope.sessionId = sessionId;
939
762
  var data = envelope.data;
940
- this._applyOverrides(data);
941
763
  if (!data || !data.eventType) {
942
- this._emit(sessionId, 'event', envelope);
764
+ this._emit('event', envelope);
943
765
  return _promise.default.resolve();
944
766
  }
767
+ this._applyOverrides(data);
945
768
  return this._getEventHandlers(data.eventType).reduce(function (promise, handler) {
946
769
  return promise.then(function () {
947
770
  var namespace = handler.namespace,
948
771
  name = handler.name;
949
772
  return new _promise.default(function (resolve) {
950
- return resolve((_this1.webex[namespace] || _this1.webex.internal[namespace])[name](data));
773
+ return resolve((_this0.webex[namespace] || _this0.webex.internal[namespace])[name](data));
951
774
  }).catch(function (reason) {
952
- return _this1.logger.error("".concat(_this1.namespace, ": error occurred in autowired event handler for ").concat(data.eventType, " from ").concat(sessionId), reason);
775
+ return _this0.logger.error("".concat(_this0.namespace, ": error occurred in autowired event handler for ").concat(data.eventType), reason);
953
776
  });
954
777
  });
955
778
  }, _promise.default.resolve()).then(function () {
956
- _this1._emit(sessionId, 'event', envelope);
957
- var _data$eventType$split = data.eventType.split('.'),
958
- _data$eventType$split2 = (0, _slicedToArray2.default)(_data$eventType$split, 1),
959
- namespace = _data$eventType$split2[0];
779
+ _this0._emit('event', event.data);
780
+ var _ref3 = data.eventType ? data.eventType.split('.') : [],
781
+ _ref4 = (0, _slicedToArray2.default)(_ref3, 1),
782
+ namespace = _ref4[0];
960
783
  if (namespace === data.eventType) {
961
- _this1._emit(sessionId, "event:".concat(namespace), envelope);
784
+ _this0._emit("event:".concat(namespace), envelope);
962
785
  } else {
963
- _this1._emit(sessionId, "event:".concat(namespace), envelope);
964
- _this1._emit(sessionId, "event:".concat(data.eventType), envelope);
786
+ _this0._emit("event:".concat(namespace), envelope);
787
+ _this0._emit("event:".concat(data.eventType), envelope);
965
788
  }
966
789
  }).catch(function (reason) {
967
- _this1.logger.error("".concat(_this1.namespace, ": error occurred processing socket message from ").concat(sessionId), reason);
790
+ _this0.logger.error("".concat(_this0.namespace, ": error occurred processing socket message"), reason);
968
791
  });
969
792
  },
970
- _setTimeOffset: function _setTimeOffset(sessionId, event) {
793
+ _setTimeOffset: function _setTimeOffset(event) {
971
794
  var wsWriteTimestamp = event.data.wsWriteTimestamp;
972
795
  if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
973
796
  this.mercuryTimeOffset = (0, _now.default)() - wsWriteTimestamp;
974
797
  }
975
798
  },
976
799
  _reconnect: function _reconnect(webSocketUrl) {
977
- var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
978
- this.logger.info("".concat(this.namespace, ": reconnecting ").concat(sessionId));
979
- return this.connect(webSocketUrl, sessionId);
800
+ this.logger.info("".concat(this.namespace, ": reconnecting"));
801
+ return this.connect(webSocketUrl);
980
802
  },
981
- version: "3.12.0-auth-prejoin-fetch.1"
803
+ version: "3.12.0-llmrefactor.10"
982
804
  }, (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));
983
- var _default2 = exports.default = Mercury;
805
+ var _default = exports.default = Mercury;
984
806
  //# sourceMappingURL=mercury.js.map