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