@webex/internal-plugin-mercury 3.11.0-webex-services-ready.1 → 3.12.0-auth-prejoin-fetch.1
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/README.md +54 -0
- package/dist/mercury.js +467 -202
- package/dist/mercury.js.map +1 -1
- package/dist/socket/constants.js +16 -0
- package/dist/socket/constants.js.map +1 -0
- package/dist/socket/socket-base.js +36 -3
- package/dist/socket/socket-base.js.map +1 -1
- package/package.json +17 -17
- package/src/mercury.js +483 -176
- package/src/socket/constants.js +6 -0
- package/src/socket/socket-base.js +40 -3
- package/test/unit/spec/mercury-events.js +35 -3
- package/test/unit/spec/mercury.js +597 -153
- package/test/unit/spec/socket.js +61 -0
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,12 +15,15 @@ _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 _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
|
|
15
20
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
21
|
+
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
|
|
16
22
|
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
|
|
17
23
|
var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
|
|
18
24
|
var _deleteProperty = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/delete-property"));
|
|
19
25
|
var _getOwnPropertyDescriptor = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor"));
|
|
26
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
|
|
20
27
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
21
28
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
22
29
|
var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/applyDecoratedDescriptor"));
|
|
@@ -34,10 +41,15 @@ var _dec, _dec2, _obj;
|
|
|
34
41
|
*/
|
|
35
42
|
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
43
|
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; }
|
|
37
47
|
var normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'pong mismatch'];
|
|
48
|
+
var MERCURY_CLOSE_4000_METRIC = 'JS_SDK_MERCURY_CLOSE_4000';
|
|
38
49
|
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
50
|
namespace: 'Mercury',
|
|
40
51
|
lastError: undefined,
|
|
52
|
+
defaultSessionId: 'mercury-default-session',
|
|
41
53
|
session: {
|
|
42
54
|
connected: {
|
|
43
55
|
default: false,
|
|
@@ -51,7 +63,30 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
51
63
|
default: false,
|
|
52
64
|
type: 'boolean'
|
|
53
65
|
},
|
|
54
|
-
|
|
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
|
+
},
|
|
55
90
|
localClusterServiceUrls: 'object',
|
|
56
91
|
mercuryTimeOffset: {
|
|
57
92
|
default: undefined,
|
|
@@ -105,60 +140,70 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
105
140
|
/**
|
|
106
141
|
* Attach event listeners to a socket.
|
|
107
142
|
* @param {Socket} socket - The socket to attach listeners to
|
|
143
|
+
* @param {sessionId} sessionId - The socket related session ID
|
|
108
144
|
* @returns {void}
|
|
109
145
|
*/
|
|
110
|
-
_attachSocketEventListeners: function _attachSocketEventListeners(socket) {
|
|
146
|
+
_attachSocketEventListeners: function _attachSocketEventListeners(socket, sessionId) {
|
|
111
147
|
var _this2 = this;
|
|
112
148
|
socket.on('close', function (event) {
|
|
113
|
-
return _this2._onclose(event, socket);
|
|
149
|
+
return _this2._onclose(sessionId, event, socket);
|
|
114
150
|
});
|
|
115
151
|
socket.on('message', function () {
|
|
116
|
-
|
|
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));
|
|
117
156
|
});
|
|
118
157
|
socket.on('pong', function () {
|
|
119
|
-
|
|
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));
|
|
120
162
|
});
|
|
121
163
|
socket.on('sequence-mismatch', function () {
|
|
122
|
-
for (var
|
|
123
|
-
args[
|
|
164
|
+
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
|
165
|
+
args[_key3] = arguments[_key3];
|
|
124
166
|
}
|
|
125
|
-
return _this2._emit.apply(_this2, ['sequence-mismatch'].concat(args));
|
|
167
|
+
return _this2._emit.apply(_this2, [sessionId, 'sequence-mismatch'].concat(args));
|
|
126
168
|
});
|
|
127
169
|
socket.on('ping-pong-latency', function () {
|
|
128
|
-
for (var
|
|
129
|
-
args[
|
|
170
|
+
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
|
171
|
+
args[_key4] = arguments[_key4];
|
|
130
172
|
}
|
|
131
|
-
return _this2._emit.apply(_this2, ['ping-pong-latency'].concat(args));
|
|
173
|
+
return _this2._emit.apply(_this2, [sessionId, 'ping-pong-latency'].concat(args));
|
|
132
174
|
});
|
|
133
175
|
},
|
|
134
176
|
/**
|
|
135
177
|
* Handle imminent shutdown by establishing a new connection while keeping
|
|
136
178
|
* the current one alive (make-before-break).
|
|
137
179
|
* Idempotent: will no-op if already in progress.
|
|
180
|
+
* @param {string} sessionId - The session ID for which the shutdown is imminent
|
|
138
181
|
* @returns {void}
|
|
139
182
|
*/
|
|
140
|
-
_handleImminentShutdown: function _handleImminentShutdown() {
|
|
183
|
+
_handleImminentShutdown: function _handleImminentShutdown(sessionId) {
|
|
141
184
|
var _this3 = this;
|
|
185
|
+
var oldSocket = this.sockets.get(sessionId);
|
|
142
186
|
try {
|
|
143
|
-
if
|
|
144
|
-
|
|
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));
|
|
145
191
|
return;
|
|
146
192
|
}
|
|
147
|
-
this._shutdownSwitchoverInProgress = true;
|
|
148
193
|
this._shutdownSwitchoverId = "".concat((0, _now.default)());
|
|
149
|
-
this.logger.info("".concat(this.namespace, ": [shutdown] switchover start, id=").concat(this._shutdownSwitchoverId));
|
|
150
|
-
this._connectWithBackoff(undefined, {
|
|
194
|
+
this.logger.info("".concat(this.namespace, ": [shutdown] switchover start, id=").concat(this._shutdownSwitchoverId, " for ").concat(sessionId));
|
|
195
|
+
this._connectWithBackoff(undefined, sessionId, {
|
|
151
196
|
isShutdownSwitchover: true,
|
|
152
197
|
attemptOptions: {
|
|
153
198
|
isShutdownSwitchover: true,
|
|
154
199
|
onSuccess: function onSuccess(newSocket, webSocketUrl) {
|
|
155
|
-
_this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover connected, url: ").concat(webSocketUrl));
|
|
156
|
-
|
|
200
|
+
_this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover connected, url: ").concat(webSocketUrl, " for ").concat(sessionId));
|
|
201
|
+
|
|
157
202
|
// Atomically switch active socket reference
|
|
158
|
-
_this3.socket =
|
|
159
|
-
_this3.connected =
|
|
203
|
+
_this3.socket = _this3.sockets.get(_this3.defaultSessionId);
|
|
204
|
+
_this3.connected = _this3.hasConnectedSockets(); // remain connected throughout
|
|
160
205
|
|
|
161
|
-
_this3._emit('event:mercury_shutdown_switchover_complete', {
|
|
206
|
+
_this3._emit(sessionId, 'event:mercury_shutdown_switchover_complete', {
|
|
162
207
|
url: webSocketUrl
|
|
163
208
|
});
|
|
164
209
|
if (oldSocket) {
|
|
@@ -167,18 +212,18 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
167
212
|
}
|
|
168
213
|
}
|
|
169
214
|
}).then(function () {
|
|
170
|
-
_this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover completed successfully"));
|
|
215
|
+
_this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover completed successfully for ").concat(sessionId));
|
|
171
216
|
}).catch(function (err) {
|
|
172
|
-
_this3.logger.info("".concat(_this3.namespace, ": [shutdown] switchover exhausted retries; will fall back to normal reconnection"), err);
|
|
173
|
-
_this3._emit('event:mercury_shutdown_switchover_failed', {
|
|
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', {
|
|
174
219
|
reason: err
|
|
175
220
|
});
|
|
176
221
|
// Old socket will eventually close with 4001, triggering normal reconnection
|
|
177
222
|
});
|
|
178
223
|
} catch (e) {
|
|
179
|
-
this.logger.error("".concat(this.namespace, ": [shutdown] error during switchover"), e);
|
|
180
|
-
this.
|
|
181
|
-
this._emit('event:mercury_shutdown_switchover_failed', {
|
|
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', {
|
|
182
227
|
reason: e
|
|
183
228
|
});
|
|
184
229
|
}
|
|
@@ -190,45 +235,154 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
190
235
|
getLastError: function getLastError() {
|
|
191
236
|
return this.lastError;
|
|
192
237
|
},
|
|
238
|
+
/**
|
|
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
|
|
249
|
+
*/
|
|
250
|
+
getSocket: function getSocket() {
|
|
251
|
+
var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
|
|
252
|
+
return this.sockets.get(sessionId);
|
|
253
|
+
},
|
|
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
|
+
*/
|
|
193
280
|
connect: function connect(webSocketUrl) {
|
|
194
281
|
var _this4 = this;
|
|
195
|
-
|
|
196
|
-
|
|
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"));
|
|
197
293
|
return _promise.default.resolve();
|
|
198
294
|
}
|
|
199
295
|
this.connecting = true;
|
|
200
|
-
this.logger.info("".concat(this.namespace, ": starting connection attempt"));
|
|
296
|
+
this.logger.info("".concat(this.namespace, ": starting connection attempt for ").concat(sessionId));
|
|
201
297
|
this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
|
|
202
|
-
|
|
203
|
-
_this4.logger.info("".concat(_this4.namespace, ": connecting"));
|
|
204
|
-
return _this4._connectWithBackoff(webSocketUrl);
|
|
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);
|
|
301
|
+
}).finally(function () {
|
|
302
|
+
_this4._connectPromises.delete(sessionId);
|
|
205
303
|
});
|
|
304
|
+
this._connectPromises.set(sessionId, connectPromise);
|
|
305
|
+
return connectPromise;
|
|
206
306
|
},
|
|
207
307
|
logout: function logout() {
|
|
208
308
|
this.logger.info("".concat(this.namespace, ": logout() called"));
|
|
209
309
|
this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
|
|
210
|
-
return this.
|
|
310
|
+
return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
|
|
211
311
|
code: 3050,
|
|
212
312
|
reason: this.config.beforeLogoutOptionsCloseReason
|
|
213
313
|
} : undefined);
|
|
214
314
|
},
|
|
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
|
+
*/
|
|
215
321
|
disconnect: function disconnect(options) {
|
|
216
322
|
var _this5 = this;
|
|
323
|
+
var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
|
|
324
|
+
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)));
|
|
217
325
|
return new _promise.default(function (resolve) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
_this5.
|
|
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);
|
|
221
337
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
_this5.
|
|
338
|
+
// Clean up any pending connection promises
|
|
339
|
+
if (_this5._connectPromises) {
|
|
340
|
+
_this5._connectPromises.delete(sessionId);
|
|
225
341
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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));
|
|
230
350
|
}
|
|
231
351
|
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
|
+
}
|
|
232
386
|
});
|
|
233
387
|
},
|
|
234
388
|
listen: function listen() {
|
|
@@ -252,7 +406,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
252
406
|
});
|
|
253
407
|
},
|
|
254
408
|
_prepareUrl: function _prepareUrl(webSocketUrl) {
|
|
255
|
-
var
|
|
409
|
+
var _this7 = this;
|
|
256
410
|
if (!webSocketUrl) {
|
|
257
411
|
webSocketUrl = this.webex.internal.device.webSocketUrl;
|
|
258
412
|
}
|
|
@@ -260,16 +414,16 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
260
414
|
if (haMessagingEnabled) {
|
|
261
415
|
var highPrioritySocketUrl;
|
|
262
416
|
try {
|
|
263
|
-
highPrioritySocketUrl =
|
|
417
|
+
highPrioritySocketUrl = _this7.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
|
|
264
418
|
} catch (e) {
|
|
265
|
-
|
|
419
|
+
_this7.logger.warn("".concat(_this7.namespace, ": error converting to high priority url"), e);
|
|
266
420
|
}
|
|
267
421
|
if (!highPrioritySocketUrl) {
|
|
268
422
|
var _url$parse;
|
|
269
423
|
var hostFromUrl = (_url$parse = _url.default.parse(webSocketUrl, true)) === null || _url$parse === void 0 ? void 0 : _url$parse.host;
|
|
270
|
-
var isValidHost =
|
|
424
|
+
var isValidHost = _this7.webex.internal.services.isValidHost(hostFromUrl);
|
|
271
425
|
if (!isValidHost) {
|
|
272
|
-
|
|
426
|
+
_this7.logger.error("".concat(_this7.namespace, ": host ").concat(hostFromUrl, " is not a valid host from host catalog"));
|
|
273
427
|
return '';
|
|
274
428
|
}
|
|
275
429
|
}
|
|
@@ -279,7 +433,7 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
279
433
|
}).then(function (wsUrl) {
|
|
280
434
|
webSocketUrl = wsUrl;
|
|
281
435
|
}).then(function () {
|
|
282
|
-
return
|
|
436
|
+
return _this7.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
|
|
283
437
|
}).then(function (webSharedMercury) {
|
|
284
438
|
if (!webSocketUrl) {
|
|
285
439
|
return '';
|
|
@@ -297,27 +451,31 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
297
451
|
});
|
|
298
452
|
(0, _deleteProperty.default)(webSocketUrl.query, 'bufferStates');
|
|
299
453
|
}
|
|
300
|
-
if ((0, _lodash.get)(
|
|
454
|
+
if ((0, _lodash.get)(_this7, 'webex.config.device.ephemeral', false)) {
|
|
301
455
|
webSocketUrl.query.multipleConnections = true;
|
|
302
456
|
}
|
|
303
457
|
webSocketUrl.query.clientTimestamp = (0, _now.default)();
|
|
458
|
+
delete webSocketUrl.search;
|
|
304
459
|
return _url.default.format(webSocketUrl);
|
|
305
460
|
});
|
|
306
461
|
},
|
|
307
|
-
_attemptConnection: function _attemptConnection(socketUrl, callback) {
|
|
308
|
-
var
|
|
309
|
-
var options = arguments.length >
|
|
462
|
+
_attemptConnection: function _attemptConnection(socketUrl, sessionId, callback) {
|
|
463
|
+
var _this8 = this;
|
|
464
|
+
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
310
465
|
var _options$isShutdownSw = options.isShutdownSwitchover,
|
|
311
466
|
isShutdownSwitchover = _options$isShutdownSw === void 0 ? false : _options$isShutdownSw,
|
|
312
467
|
_options$onSuccess = options.onSuccess,
|
|
313
468
|
onSuccess = _options$onSuccess === void 0 ? null : _options$onSuccess;
|
|
314
469
|
var socket = new _socket.default();
|
|
470
|
+
socket.connecting = true;
|
|
315
471
|
var newWSUrl;
|
|
316
|
-
this._attachSocketEventListeners(socket);
|
|
472
|
+
this._attachSocketEventListeners(socket, sessionId);
|
|
473
|
+
var backoffCall = isShutdownSwitchover ? this._shutdownSwitchoverBackoffCalls.get(sessionId) : this.backoffCalls.get(sessionId);
|
|
317
474
|
|
|
318
475
|
// Check appropriate backoff call based on connection type
|
|
319
|
-
if (
|
|
320
|
-
var
|
|
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);
|
|
321
479
|
var err = new Error(msg);
|
|
322
480
|
this.logger.info(msg);
|
|
323
481
|
|
|
@@ -325,24 +483,15 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
325
483
|
callback(err);
|
|
326
484
|
return _promise.default.reject(err);
|
|
327
485
|
}
|
|
328
|
-
if (!isShutdownSwitchover && !this.backoffCall) {
|
|
329
|
-
var _msg = "".concat(this.namespace, ": prevent socket open when backoffCall no longer defined");
|
|
330
|
-
var _err = new Error(_msg);
|
|
331
|
-
this.logger.info(_msg);
|
|
332
|
-
|
|
333
|
-
// Call the callback with the error before rejecting
|
|
334
|
-
callback(_err);
|
|
335
|
-
return _promise.default.reject(_err);
|
|
336
|
-
}
|
|
337
486
|
|
|
338
487
|
// For shutdown switchover, don't set socket yet (make-before-break)
|
|
339
488
|
// For normal connection, set socket before opening to allow disconnect() to close it
|
|
340
489
|
if (!isShutdownSwitchover) {
|
|
341
|
-
this.
|
|
490
|
+
this.sockets.set(sessionId, socket);
|
|
342
491
|
}
|
|
343
|
-
return this._prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover).then(function (webSocketUrl) {
|
|
492
|
+
return this._prepareAndOpenSocket(socket, socketUrl, sessionId, isShutdownSwitchover).then(function (webSocketUrl) {
|
|
344
493
|
newWSUrl = webSocketUrl;
|
|
345
|
-
|
|
494
|
+
_this8.logger.info("".concat(_this8.namespace, ": ").concat(isShutdownSwitchover ? '[shutdown] switchover' : '', " connected to mercury, success, action: connected for ").concat(sessionId, ", url: ").concat(newWSUrl));
|
|
346
495
|
|
|
347
496
|
// Custom success handler for shutdown switchover
|
|
348
497
|
if (onSuccess) {
|
|
@@ -353,46 +502,46 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
353
502
|
|
|
354
503
|
// Default behavior for normal connection
|
|
355
504
|
callback();
|
|
356
|
-
return
|
|
505
|
+
return _this8.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
|
|
357
506
|
if (haMessagingEnabled) {
|
|
358
|
-
return
|
|
507
|
+
return _this8.webex.internal.device.refresh();
|
|
359
508
|
}
|
|
360
509
|
return _promise.default.resolve();
|
|
361
510
|
});
|
|
362
511
|
}).catch(function (reason) {
|
|
363
|
-
var _this7$backoffCall, _this7$backoffCall3;
|
|
364
512
|
// For shutdown, simpler error handling - just callback for retry
|
|
365
513
|
if (isShutdownSwitchover) {
|
|
366
|
-
|
|
514
|
+
_this8.logger.info("".concat(_this8.namespace, ": [shutdown] switchover attempt failed for ").concat(sessionId), reason);
|
|
367
515
|
return callback(reason);
|
|
368
516
|
}
|
|
369
517
|
|
|
370
518
|
// Normal connection error handling (existing complex logic)
|
|
371
|
-
|
|
519
|
+
_this8.lastError = reason; // remember the last error
|
|
372
520
|
|
|
521
|
+
var backoffCallNormal = _this8.backoffCalls.get(sessionId);
|
|
373
522
|
// Suppress connection errors that appear to be network related. This
|
|
374
523
|
// may end up suppressing metrics during outages, but we might not care
|
|
375
524
|
// (especially since many of our outages happen in a way that client
|
|
376
525
|
// metrics can't be trusted).
|
|
377
|
-
if (reason.code !== 1006 &&
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
retries:
|
|
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()
|
|
381
530
|
});
|
|
382
531
|
}
|
|
383
|
-
|
|
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 : '');
|
|
384
533
|
// UnknownResponse is produced by IE for any 4XXX; treated it like a bad
|
|
385
534
|
// web socket url and let WDM handle the token checking
|
|
386
535
|
if (reason instanceof _errors.UnknownResponse) {
|
|
387
|
-
|
|
388
|
-
return
|
|
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 () {
|
|
389
538
|
return callback(reason);
|
|
390
539
|
});
|
|
391
540
|
}
|
|
392
541
|
// NotAuthorized implies expired token
|
|
393
542
|
if (reason instanceof _errors.NotAuthorized) {
|
|
394
|
-
|
|
395
|
-
return
|
|
543
|
+
_this8.logger.info("".concat(_this8.namespace, ": received authorization error for ").concat(sessionId, ", reauthorizing"));
|
|
544
|
+
return _this8.webex.credentials.refresh({
|
|
396
545
|
force: true
|
|
397
546
|
}).then(function () {
|
|
398
547
|
return callback(reason);
|
|
@@ -407,15 +556,20 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
407
556
|
// BadRequest implies current credentials are for a Service Account
|
|
408
557
|
// Forbidden implies current user is not entitle for Webex
|
|
409
558
|
if (reason instanceof _errors.BadRequest || reason instanceof _errors.Forbidden) {
|
|
410
|
-
|
|
411
|
-
|
|
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();
|
|
412
561
|
return callback(reason);
|
|
413
562
|
}
|
|
414
563
|
if (reason instanceof _errors.ConnectionError) {
|
|
415
|
-
return
|
|
564
|
+
return _this8.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
|
|
565
|
+
var wsUrl = newWSUrl || reason.webSocketUrl;
|
|
416
566
|
if (haMessagingEnabled) {
|
|
417
|
-
|
|
418
|
-
|
|
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));
|
|
568
|
+
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);
|
|
571
|
+
}
|
|
572
|
+
_this8.logger.info("".concat(_this8.namespace, ": no socket url available to mark as failed for ").concat(sessionId, " due to connection error"));
|
|
419
573
|
}
|
|
420
574
|
return null;
|
|
421
575
|
}).then(function () {
|
|
@@ -424,129 +578,186 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
424
578
|
}
|
|
425
579
|
return callback(reason);
|
|
426
580
|
}).catch(function (reason) {
|
|
427
|
-
|
|
581
|
+
_this8.logger.error("".concat(_this8.namespace, ": failed to handle connection failure for ").concat(sessionId), reason);
|
|
428
582
|
callback(reason);
|
|
429
583
|
});
|
|
430
584
|
},
|
|
431
|
-
_prepareAndOpenSocket: function _prepareAndOpenSocket(socket, socketUrl) {
|
|
432
|
-
var
|
|
433
|
-
var isShutdownSwitchover = arguments.length >
|
|
585
|
+
_prepareAndOpenSocket: function _prepareAndOpenSocket(socket, socketUrl, sessionId) {
|
|
586
|
+
var _this9 = this;
|
|
587
|
+
var isShutdownSwitchover = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
434
588
|
var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
|
|
435
589
|
return _promise.default.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
|
|
436
590
|
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
|
|
437
591
|
webSocketUrl = _ref2[0],
|
|
438
592
|
token = _ref2[1];
|
|
439
593
|
var options = {
|
|
440
|
-
forceCloseDelay:
|
|
441
|
-
pingInterval:
|
|
442
|
-
pongTimeout:
|
|
594
|
+
forceCloseDelay: _this9.config.forceCloseDelay,
|
|
595
|
+
pingInterval: _this9.config.pingInterval,
|
|
596
|
+
pongTimeout: _this9.config.pongTimeout,
|
|
443
597
|
token: token.toString(),
|
|
444
|
-
trackingId: "".concat(
|
|
445
|
-
logger:
|
|
598
|
+
trackingId: "".concat(_this9.webex.sessionId, "_").concat((0, _now.default)()),
|
|
599
|
+
logger: _this9.logger
|
|
446
600
|
};
|
|
447
|
-
if (
|
|
601
|
+
if (_this9.webex.config.defaultMercuryOptions) {
|
|
448
602
|
var customOptionsMsg = isShutdownSwitchover ? 'setting custom options for switchover' : 'setting custom options';
|
|
449
|
-
|
|
450
|
-
options = _objectSpread(_objectSpread({}, options),
|
|
603
|
+
_this9.logger.info("".concat(_this9.namespace, ": ").concat(customOptionsMsg));
|
|
604
|
+
options = _objectSpread(_objectSpread({}, options), _this9.webex.config.defaultMercuryOptions);
|
|
451
605
|
}
|
|
452
|
-
|
|
606
|
+
|
|
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);
|
|
453
620
|
return socket.open(webSocketUrl, options).then(function () {
|
|
454
621
|
return webSocketUrl;
|
|
622
|
+
}).catch(function (err) {
|
|
623
|
+
err.webSocketUrl = webSocketUrl;
|
|
624
|
+
return _promise.default.reject(err);
|
|
455
625
|
});
|
|
456
626
|
});
|
|
457
627
|
},
|
|
458
|
-
_connectWithBackoff: function _connectWithBackoff(webSocketUrl) {
|
|
459
|
-
var
|
|
460
|
-
var context = arguments.length >
|
|
628
|
+
_connectWithBackoff: function _connectWithBackoff(webSocketUrl, sessionId) {
|
|
629
|
+
var _this0 = this;
|
|
630
|
+
var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
461
631
|
var _context$isShutdownSw = context.isShutdownSwitchover,
|
|
462
632
|
isShutdownSwitchover = _context$isShutdownSw === void 0 ? false : _context$isShutdownSw,
|
|
463
633
|
_context$attemptOptio = context.attemptOptions,
|
|
464
634
|
attemptOptions = _context$attemptOptio === void 0 ? {} : _context$attemptOptio;
|
|
465
635
|
return new _promise.default(function (resolve, reject) {
|
|
466
|
-
// eslint gets confused about whether
|
|
636
|
+
// eslint gets confused about whether call is actually used
|
|
467
637
|
// eslint-disable-next-line prefer-const
|
|
468
638
|
var call;
|
|
469
639
|
var onComplete = function onComplete(err) {
|
|
470
|
-
|
|
640
|
+
var sid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : sessionId;
|
|
471
641
|
if (isShutdownSwitchover) {
|
|
472
|
-
|
|
473
|
-
_this9._shutdownSwitchoverBackoffCall = undefined;
|
|
642
|
+
_this0._shutdownSwitchoverBackoffCalls.delete(sid);
|
|
474
643
|
} else {
|
|
475
|
-
|
|
476
|
-
_this9.backoffCall = undefined;
|
|
644
|
+
_this0.backoffCalls.delete(sid);
|
|
477
645
|
}
|
|
646
|
+
var sessionSocket = _this0.sockets.get(sid);
|
|
478
647
|
if (err) {
|
|
479
648
|
var msg = isShutdownSwitchover ? "[shutdown] switchover failed after ".concat(call.getNumRetries(), " retries") : "failed to connect after ".concat(call.getNumRetries(), " retries");
|
|
480
|
-
|
|
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
|
+
}
|
|
481
654
|
return reject(err);
|
|
482
655
|
}
|
|
483
656
|
|
|
657
|
+
// Update overall connected status
|
|
658
|
+
if (sessionSocket) {
|
|
659
|
+
sessionSocket.connecting = false;
|
|
660
|
+
sessionSocket.connected = true;
|
|
661
|
+
}
|
|
484
662
|
// Default success handling for normal connections
|
|
485
663
|
if (!isShutdownSwitchover) {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
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
|
+
}
|
|
490
671
|
}
|
|
491
672
|
return resolve();
|
|
492
673
|
};
|
|
493
|
-
|
|
494
674
|
// eslint-disable-next-line prefer-reflect
|
|
495
675
|
call = _backoff.default.call(function (callback) {
|
|
496
676
|
var attemptNum = call.getNumRetries();
|
|
497
677
|
var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
},
|
|
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
|
+
});
|
|
501
683
|
call.setStrategy(new _backoff.default.ExponentialStrategy({
|
|
502
|
-
initialDelay:
|
|
503
|
-
maxDelay:
|
|
684
|
+
initialDelay: _this0.config.backoffTimeReset,
|
|
685
|
+
maxDelay: _this0.config.backoffTimeMax
|
|
504
686
|
}));
|
|
505
|
-
if (
|
|
506
|
-
call.failAfter(
|
|
507
|
-
} else if (
|
|
508
|
-
call.failAfter(
|
|
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);
|
|
509
699
|
}
|
|
510
700
|
call.on('abort', function () {
|
|
511
701
|
var msg = isShutdownSwitchover ? 'Shutdown Switchover' : 'Connection';
|
|
512
|
-
|
|
513
|
-
reject(new Error("Mercury ".concat(msg, " Aborted")));
|
|
702
|
+
_this0.logger.info("".concat(_this0.namespace, ": ").concat(msg, " aborted for ").concat(sessionId));
|
|
703
|
+
reject(new Error("Mercury ".concat(msg, " Aborted for ").concat(sessionId)));
|
|
514
704
|
});
|
|
515
705
|
call.on('callback', function (err) {
|
|
516
706
|
if (err) {
|
|
517
707
|
var number = call.getNumRetries();
|
|
518
|
-
var delay = Math.min(call.strategy_.nextBackoffDelay_,
|
|
708
|
+
var delay = Math.min(call.strategy_.nextBackoffDelay_, _this0.config.backoffTimeMax);
|
|
519
709
|
var logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : '';
|
|
520
|
-
|
|
710
|
+
_this0.logger.info("".concat(_this0.namespace, ": ").concat(logPrefix, " failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms for ").concat(sessionId));
|
|
521
711
|
/* istanbul ignore if */
|
|
522
712
|
if (process.env.NODE_ENV === 'development') {
|
|
523
|
-
|
|
713
|
+
_this0.logger.debug("".concat(_this0.namespace, ": "), err, err.stack);
|
|
524
714
|
}
|
|
525
715
|
return;
|
|
526
716
|
}
|
|
527
|
-
|
|
717
|
+
_this0.logger.info("".concat(_this0.namespace, ": connected ").concat(sessionId));
|
|
528
718
|
});
|
|
529
|
-
|
|
530
|
-
// Store backoff call reference BEFORE starting (so it's available in _attemptConnection)
|
|
531
|
-
if (isShutdownSwitchover) {
|
|
532
|
-
_this9._shutdownSwitchoverBackoffCall = call;
|
|
533
|
-
} else {
|
|
534
|
-
_this9.backoffCall = call;
|
|
535
|
-
}
|
|
536
719
|
call.start();
|
|
537
720
|
});
|
|
538
721
|
},
|
|
539
722
|
_emit: function _emit() {
|
|
540
|
-
for (var
|
|
541
|
-
args[
|
|
723
|
+
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
|
|
724
|
+
args[_key5] = arguments[_key5];
|
|
542
725
|
}
|
|
543
726
|
try {
|
|
544
|
-
|
|
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
|
+
}
|
|
545
746
|
} catch (error) {
|
|
546
|
-
|
|
747
|
+
// Safely handle errors without causing additional issues during cleanup
|
|
748
|
+
try {
|
|
749
|
+
this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
|
|
750
|
+
} catch (logError) {
|
|
751
|
+
// If even logging fails, just ignore to prevent cascading errors during cleanup
|
|
752
|
+
// eslint-disable-next-line no-console
|
|
753
|
+
console.error('Mercury _emit error handling failed:', logError);
|
|
754
|
+
}
|
|
547
755
|
}
|
|
548
756
|
},
|
|
549
757
|
_getEventHandlers: function _getEventHandlers(eventType) {
|
|
758
|
+
if (!eventType) {
|
|
759
|
+
return [];
|
|
760
|
+
}
|
|
550
761
|
var _eventType$split = eventType.split('.'),
|
|
551
762
|
_eventType$split2 = (0, _slicedToArray2.default)(_eventType$split, 2),
|
|
552
763
|
namespace = _eventType$split2[0],
|
|
@@ -564,33 +775,63 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
564
775
|
}
|
|
565
776
|
return handlers;
|
|
566
777
|
},
|
|
567
|
-
|
|
778
|
+
_submitMercuryClose4000Metric: function _submitMercuryClose4000Metric(sessionId, event, options) {
|
|
779
|
+
var action = options.action,
|
|
780
|
+
isActiveSocket = options.isActiveSocket,
|
|
781
|
+
messageType = options.messageType;
|
|
782
|
+
try {
|
|
783
|
+
this.webex.internal.metrics.submitClientMetrics(MERCURY_CLOSE_4000_METRIC, {
|
|
784
|
+
fields: {
|
|
785
|
+
action: action,
|
|
786
|
+
close_code: event.code,
|
|
787
|
+
close_reason: event.reason || '',
|
|
788
|
+
is_active_socket: isActiveSocket,
|
|
789
|
+
message_type: messageType,
|
|
790
|
+
session_id: sessionId
|
|
791
|
+
},
|
|
792
|
+
tags: {
|
|
793
|
+
action: action,
|
|
794
|
+
message_type: messageType
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
} catch (error) {
|
|
798
|
+
this.logger.warn("".concat(this.namespace, ": failed to submit Mercury 4000 close metric"), error);
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
_onclose: function _onclose(sessionId, event, sourceSocket) {
|
|
568
802
|
// I don't see any way to avoid the complexity or statement count in here.
|
|
569
803
|
/* eslint complexity: [0] */
|
|
570
804
|
|
|
571
805
|
try {
|
|
572
|
-
var isActiveSocket = sourceSocket === this.socket;
|
|
573
806
|
var reason = event.reason && event.reason.toLowerCase();
|
|
574
|
-
var
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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);
|
|
582
819
|
if (isActiveSocket) {
|
|
583
820
|
// Only tear down state if the currently active socket closed
|
|
584
|
-
if (
|
|
585
|
-
|
|
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);
|
|
586
831
|
}
|
|
587
|
-
this.unset('socket');
|
|
588
|
-
this.connected = false;
|
|
589
|
-
this._emit('offline', event);
|
|
590
|
-
this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
|
|
591
832
|
} else {
|
|
592
833
|
// Old socket closed; do not flip connection state
|
|
593
|
-
this.logger.info("".concat(this.namespace, ": [shutdown] non-active socket closed, code=").concat(event.code));
|
|
834
|
+
this.logger.info("".concat(this.namespace, ": [shutdown] non-active socket closed, code=").concat(event.code, " for ").concat(sessionId));
|
|
594
835
|
// Clean up listeners from old socket now that it's closed
|
|
595
836
|
if (sourceSocket) {
|
|
596
837
|
sourceSocket.removeAllListeners();
|
|
@@ -599,14 +840,31 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
599
840
|
switch (event.code) {
|
|
600
841
|
case 1003:
|
|
601
842
|
// metric: disconnect
|
|
602
|
-
this.logger.info("".concat(this.namespace, ": Mercury service rejected last message; will not reconnect: ").concat(event.reason));
|
|
603
|
-
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
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);
|
|
604
845
|
break;
|
|
605
846
|
case 4000:
|
|
606
847
|
// metric: disconnect
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
848
|
+
if (reason === 'replaced') {
|
|
849
|
+
this._submitMercuryClose4000Metric(sessionId, event, {
|
|
850
|
+
action: 'no_action',
|
|
851
|
+
isActiveSocket: isActiveSocket,
|
|
852
|
+
messageType: 'replaced'
|
|
853
|
+
});
|
|
854
|
+
this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " replaced; will not reconnect"));
|
|
855
|
+
if (isActiveSocket) this._emit(sessionId, 'offline.replaced', event);
|
|
856
|
+
} else {
|
|
857
|
+
this._submitMercuryClose4000Metric(sessionId, event, {
|
|
858
|
+
action: isActiveSocket ? 'reconnect' : 'ignore_non_active',
|
|
859
|
+
isActiveSocket: isActiveSocket,
|
|
860
|
+
messageType: 'other'
|
|
861
|
+
});
|
|
862
|
+
this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected with 4000: ").concat(event.reason, "; reconnecting"));
|
|
863
|
+
if (isActiveSocket) {
|
|
864
|
+
this._emit(sessionId, 'offline.transient', event);
|
|
865
|
+
this._reconnect(socketUrl, sessionId);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
610
868
|
break;
|
|
611
869
|
case 4001:
|
|
612
870
|
// replaced during shutdown
|
|
@@ -614,23 +872,23 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
614
872
|
// Server closed active socket with 4001, meaning it expected this connection
|
|
615
873
|
// to be replaced, but the switchover in _handleImminentShutdown failed.
|
|
616
874
|
// This is a permanent failure - do not reconnect.
|
|
617
|
-
this.logger.warn("".concat(this.namespace, ": active socket closed with 4001; shutdown switchover failed"));
|
|
618
|
-
this._emit('offline.permanent', event);
|
|
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);
|
|
619
877
|
} else {
|
|
620
878
|
// Expected: old socket closed after successful switchover
|
|
621
|
-
this.logger.info("".concat(this.namespace, ": old socket closed with 4001 (replaced during shutdown); no reconnect needed"));
|
|
622
|
-
this._emit('offline.replaced', event);
|
|
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);
|
|
623
881
|
}
|
|
624
882
|
break;
|
|
625
883
|
case 1001:
|
|
626
884
|
case 1005:
|
|
627
885
|
case 1006:
|
|
628
886
|
case 1011:
|
|
629
|
-
this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
|
|
887
|
+
this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
|
|
630
888
|
if (isActiveSocket) {
|
|
631
|
-
this._emit('offline.transient', event);
|
|
632
|
-
this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting active socket to recover"));
|
|
633
|
-
this._reconnect(socketUrl);
|
|
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);
|
|
634
892
|
}
|
|
635
893
|
// metric: disconnect
|
|
636
894
|
// if (code == 1011 && reason !== ping error) metric: unexpected disconnect
|
|
@@ -639,81 +897,88 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
|
|
|
639
897
|
case 3050:
|
|
640
898
|
// 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
|
|
641
899
|
if (normalReconnectReasons.includes(reason)) {
|
|
642
|
-
this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
|
|
900
|
+
this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
|
|
643
901
|
if (isActiveSocket) {
|
|
644
|
-
this._emit('offline.transient', event);
|
|
645
|
-
this.logger.info("".concat(this.namespace, ": [shutdown] reconnecting due to normal close"));
|
|
646
|
-
this._reconnect(socketUrl);
|
|
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);
|
|
647
905
|
}
|
|
648
906
|
// metric: disconnect
|
|
649
907
|
// if (reason === done forced) metric: force closure
|
|
650
908
|
} else {
|
|
651
|
-
this.logger.info("".concat(this.namespace, ": socket disconnected; will not reconnect: ").concat(event.reason));
|
|
652
|
-
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
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);
|
|
653
911
|
}
|
|
654
912
|
break;
|
|
655
913
|
default:
|
|
656
|
-
this.logger.info("".concat(this.namespace, ": socket disconnected unexpectedly; will not reconnect"));
|
|
914
|
+
this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected unexpectedly; will not reconnect"));
|
|
657
915
|
// unexpected disconnect
|
|
658
|
-
if (isActiveSocket) this._emit('offline.permanent', event);
|
|
916
|
+
if (isActiveSocket) this._emit(sessionId, 'offline.permanent', event);
|
|
659
917
|
}
|
|
660
918
|
} catch (error) {
|
|
661
|
-
this.logger.error("".concat(this.namespace, ": error occurred in close handler"), error);
|
|
919
|
+
this.logger.error("".concat(this.namespace, ": error occurred in close handler for ").concat(sessionId), error);
|
|
662
920
|
}
|
|
663
921
|
},
|
|
664
|
-
_onmessage: function _onmessage(event) {
|
|
665
|
-
var
|
|
666
|
-
this._setTimeOffset(event);
|
|
922
|
+
_onmessage: function _onmessage(sessionId, event) {
|
|
923
|
+
var _this1 = this;
|
|
924
|
+
this._setTimeOffset(sessionId, event);
|
|
667
925
|
var envelope = event.data;
|
|
668
926
|
if (process.env.ENABLE_MERCURY_LOGGING) {
|
|
669
|
-
this.logger.debug("".concat(this.namespace, ": message envelope: "), envelope);
|
|
927
|
+
this.logger.debug("".concat(this.namespace, ": message envelope from ").concat(sessionId, ": "), envelope);
|
|
670
928
|
}
|
|
929
|
+
envelope.sessionId = sessionId;
|
|
671
930
|
|
|
672
931
|
// Handle shutdown message shape: { type: 'shutdown' }
|
|
673
932
|
if (envelope && envelope.type === 'shutdown') {
|
|
674
|
-
this.logger.info("".concat(this.namespace, ": [shutdown] imminent shutdown message received"));
|
|
675
|
-
this._emit('event:mercury_shutdown_imminent', envelope);
|
|
676
|
-
this._handleImminentShutdown();
|
|
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);
|
|
677
936
|
return _promise.default.resolve();
|
|
678
937
|
}
|
|
938
|
+
envelope.sessionId = sessionId;
|
|
679
939
|
var data = envelope.data;
|
|
680
940
|
this._applyOverrides(data);
|
|
941
|
+
if (!data || !data.eventType) {
|
|
942
|
+
this._emit(sessionId, 'event', envelope);
|
|
943
|
+
return _promise.default.resolve();
|
|
944
|
+
}
|
|
681
945
|
return this._getEventHandlers(data.eventType).reduce(function (promise, handler) {
|
|
682
946
|
return promise.then(function () {
|
|
683
947
|
var namespace = handler.namespace,
|
|
684
948
|
name = handler.name;
|
|
685
949
|
return new _promise.default(function (resolve) {
|
|
686
|
-
return resolve((
|
|
950
|
+
return resolve((_this1.webex[namespace] || _this1.webex.internal[namespace])[name](data));
|
|
687
951
|
}).catch(function (reason) {
|
|
688
|
-
return
|
|
952
|
+
return _this1.logger.error("".concat(_this1.namespace, ": error occurred in autowired event handler for ").concat(data.eventType, " from ").concat(sessionId), reason);
|
|
689
953
|
});
|
|
690
954
|
});
|
|
691
955
|
}, _promise.default.resolve()).then(function () {
|
|
692
|
-
|
|
956
|
+
_this1._emit(sessionId, 'event', envelope);
|
|
693
957
|
var _data$eventType$split = data.eventType.split('.'),
|
|
694
958
|
_data$eventType$split2 = (0, _slicedToArray2.default)(_data$eventType$split, 1),
|
|
695
959
|
namespace = _data$eventType$split2[0];
|
|
696
960
|
if (namespace === data.eventType) {
|
|
697
|
-
|
|
961
|
+
_this1._emit(sessionId, "event:".concat(namespace), envelope);
|
|
698
962
|
} else {
|
|
699
|
-
|
|
700
|
-
|
|
963
|
+
_this1._emit(sessionId, "event:".concat(namespace), envelope);
|
|
964
|
+
_this1._emit(sessionId, "event:".concat(data.eventType), envelope);
|
|
701
965
|
}
|
|
702
966
|
}).catch(function (reason) {
|
|
703
|
-
|
|
967
|
+
_this1.logger.error("".concat(_this1.namespace, ": error occurred processing socket message from ").concat(sessionId), reason);
|
|
704
968
|
});
|
|
705
969
|
},
|
|
706
|
-
_setTimeOffset: function _setTimeOffset(event) {
|
|
970
|
+
_setTimeOffset: function _setTimeOffset(sessionId, event) {
|
|
707
971
|
var wsWriteTimestamp = event.data.wsWriteTimestamp;
|
|
708
972
|
if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
|
|
709
973
|
this.mercuryTimeOffset = (0, _now.default)() - wsWriteTimestamp;
|
|
710
974
|
}
|
|
711
975
|
},
|
|
712
976
|
_reconnect: function _reconnect(webSocketUrl) {
|
|
713
|
-
|
|
714
|
-
|
|
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);
|
|
715
980
|
},
|
|
716
|
-
version: "3.
|
|
717
|
-
}, (0, _applyDecoratedDescriptor2.default)(_obj, "
|
|
718
|
-
var
|
|
981
|
+
version: "3.12.0-auth-prejoin-fetch.1"
|
|
982
|
+
}, (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;
|
|
719
984
|
//# sourceMappingURL=mercury.js.map
|