@webex/internal-plugin-mercury 2.60.0 → 2.60.1-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/errors.js +8 -11
- package/dist/errors.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mercury.js +50 -62
- package/dist/mercury.js.map +1 -1
- package/dist/socket/socket-base.js +47 -42
- package/dist/socket/socket-base.js.map +1 -1
- package/dist/socket/socket.js +1 -2
- package/dist/socket/socket.js.map +1 -1
- package/dist/socket/socket.shim.js +1 -2
- package/dist/socket/socket.shim.js.map +1 -1
- package/package.json +25 -24
- package/src/mercury.js +42 -51
- package/src/socket/socket-base.js +50 -27
- package/test/integration/spec/webex.js +3 -2
- package/test/unit/spec/mercury.js +13 -4
|
@@ -32,6 +32,5 @@ _socketBase.default.getWebSocketConstructor = function getWebSocketConstructor()
|
|
|
32
32
|
}
|
|
33
33
|
return ws;
|
|
34
34
|
};
|
|
35
|
-
var _default = _socketBase.default;
|
|
36
|
-
exports.default = _default;
|
|
35
|
+
var _default = exports.default = _socketBase.default;
|
|
37
36
|
//# sourceMappingURL=socket.shim.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_socketBase","_interopRequireDefault","require","Socket","getWebSocketConstructor","ws","WebSocket","MozWebSocket","global","window","self","_default","exports","default"],"sources":["socket.shim.js"],"sourcesContent":["/* eslint-disable no-restricted-globals */\n\n/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-env browser */\n\nimport Socket from './socket-base';\n\nSocket.getWebSocketConstructor = function getWebSocketConstructor() {\n // Grabed from https://github.com/heineiuo/isomorphic-ws/blob/9b977394ac875638c045fd9cf774ed418484b394/browser.js\n let ws;\n\n if (typeof WebSocket !== 'undefined') {\n ws = WebSocket;\n } else if (typeof MozWebSocket !== 'undefined') {\n // eslint-disable-next-line no-undef\n ws = MozWebSocket;\n } else if (typeof global !== 'undefined') {\n ws = global.WebSocket || global.MozWebSocket;\n } else if (typeof window !== 'undefined') {\n ws = window.WebSocket || window.MozWebSocket;\n } else if (typeof self !== 'undefined') {\n ws = self.WebSocket || self.MozWebSocket;\n }\n\n return ws;\n};\n\nexport default Socket;\n"],"mappings":";;;;;;;;AAQA,IAAAA,WAAA,GAAAC,sBAAA,CAAAC,OAAA;AARA;;AAEA;AACA;AACA;;AAEA;;AAIAC,mBAAM,CAACC,uBAAuB,GAAG,SAASA,uBAAuBA,CAAA,EAAG;EAClE;EACA,IAAIC,EAAE;EAEN,IAAI,OAAOC,SAAS,KAAK,WAAW,EAAE;IACpCD,EAAE,GAAGC,SAAS;EAChB,CAAC,MAAM,IAAI,OAAOC,YAAY,KAAK,WAAW,EAAE;IAC9C;IACAF,EAAE,GAAGE,YAAY;EACnB,CAAC,MAAM,IAAI,OAAOC,MAAM,KAAK,WAAW,EAAE;IACxCH,EAAE,GAAGG,MAAM,CAACF,SAAS,IAAIE,MAAM,CAACD,YAAY;EAC9C,CAAC,MAAM,IAAI,OAAOE,MAAM,KAAK,WAAW,EAAE;IACxCJ,EAAE,GAAGI,MAAM,CAACH,SAAS,IAAIG,MAAM,CAACF,YAAY;EAC9C,CAAC,MAAM,IAAI,OAAOG,IAAI,KAAK,WAAW,EAAE;IACtCL,EAAE,GAAGK,IAAI,CAACJ,SAAS,IAAII,IAAI,CAACH,YAAY;EAC1C;EAEA,OAAOF,EAAE;AACX,CAAC;AAAC,IAAAM,QAAA,
|
|
1
|
+
{"version":3,"names":["_socketBase","_interopRequireDefault","require","Socket","getWebSocketConstructor","ws","WebSocket","MozWebSocket","global","window","self","_default","exports","default"],"sources":["socket.shim.js"],"sourcesContent":["/* eslint-disable no-restricted-globals */\n\n/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-env browser */\n\nimport Socket from './socket-base';\n\nSocket.getWebSocketConstructor = function getWebSocketConstructor() {\n // Grabed from https://github.com/heineiuo/isomorphic-ws/blob/9b977394ac875638c045fd9cf774ed418484b394/browser.js\n let ws;\n\n if (typeof WebSocket !== 'undefined') {\n ws = WebSocket;\n } else if (typeof MozWebSocket !== 'undefined') {\n // eslint-disable-next-line no-undef\n ws = MozWebSocket;\n } else if (typeof global !== 'undefined') {\n ws = global.WebSocket || global.MozWebSocket;\n } else if (typeof window !== 'undefined') {\n ws = window.WebSocket || window.MozWebSocket;\n } else if (typeof self !== 'undefined') {\n ws = self.WebSocket || self.MozWebSocket;\n }\n\n return ws;\n};\n\nexport default Socket;\n"],"mappings":";;;;;;;;AAQA,IAAAA,WAAA,GAAAC,sBAAA,CAAAC,OAAA;AARA;;AAEA;AACA;AACA;;AAEA;;AAIAC,mBAAM,CAACC,uBAAuB,GAAG,SAASA,uBAAuBA,CAAA,EAAG;EAClE;EACA,IAAIC,EAAE;EAEN,IAAI,OAAOC,SAAS,KAAK,WAAW,EAAE;IACpCD,EAAE,GAAGC,SAAS;EAChB,CAAC,MAAM,IAAI,OAAOC,YAAY,KAAK,WAAW,EAAE;IAC9C;IACAF,EAAE,GAAGE,YAAY;EACnB,CAAC,MAAM,IAAI,OAAOC,MAAM,KAAK,WAAW,EAAE;IACxCH,EAAE,GAAGG,MAAM,CAACF,SAAS,IAAIE,MAAM,CAACD,YAAY;EAC9C,CAAC,MAAM,IAAI,OAAOE,MAAM,KAAK,WAAW,EAAE;IACxCJ,EAAE,GAAGI,MAAM,CAACH,SAAS,IAAIG,MAAM,CAACF,YAAY;EAC9C,CAAC,MAAM,IAAI,OAAOG,IAAI,KAAK,WAAW,EAAE;IACtCL,EAAE,GAAGK,IAAI,CAACJ,SAAS,IAAII,IAAI,CAACH,YAAY;EAC1C;EAEA,OAAOF,EAAE;AACX,CAAC;AAAC,IAAAM,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEaV,mBAAM"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/internal-plugin-mercury",
|
|
3
|
-
"version": "2.60.0",
|
|
4
3
|
"description": "",
|
|
5
4
|
"license": "MIT",
|
|
6
5
|
"main": "dist/index.js",
|
|
@@ -11,7 +10,7 @@
|
|
|
11
10
|
"directory": "packages/@webex/internal-plugin-mercury"
|
|
12
11
|
},
|
|
13
12
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
13
|
+
"node": ">=16"
|
|
15
14
|
},
|
|
16
15
|
"browser": {
|
|
17
16
|
"./dist/socket/socket.js": "./dist/socket/socket.shim.js",
|
|
@@ -26,31 +25,31 @@
|
|
|
26
25
|
"devDependencies": {
|
|
27
26
|
"@babel/core": "^7.17.10",
|
|
28
27
|
"@sinonjs/fake-timers": "^6.0.1",
|
|
29
|
-
"@webex/babel-config-legacy": "
|
|
30
|
-
"@webex/eslint-config-legacy": "
|
|
31
|
-
"@webex/jest-config-legacy": "
|
|
32
|
-
"@webex/legacy-tools": "
|
|
33
|
-
"@webex/test-helper-chai": "2.60.
|
|
34
|
-
"@webex/test-helper-mocha": "2.60.
|
|
35
|
-
"@webex/test-helper-mock-webex": "2.60.
|
|
36
|
-
"@webex/test-helper-test-users": "2.60.
|
|
28
|
+
"@webex/babel-config-legacy": "0.0.0",
|
|
29
|
+
"@webex/eslint-config-legacy": "0.0.0",
|
|
30
|
+
"@webex/jest-config-legacy": "0.0.0",
|
|
31
|
+
"@webex/legacy-tools": "0.0.0",
|
|
32
|
+
"@webex/test-helper-chai": "2.60.1-next.2",
|
|
33
|
+
"@webex/test-helper-mocha": "2.60.1-next.2",
|
|
34
|
+
"@webex/test-helper-mock-webex": "2.60.1-next.2",
|
|
35
|
+
"@webex/test-helper-test-users": "2.60.1-next.2",
|
|
37
36
|
"eslint": "^8.24.0",
|
|
38
37
|
"prettier": "^2.7.1",
|
|
39
38
|
"sinon": "^9.2.4"
|
|
40
39
|
},
|
|
41
40
|
"dependencies": {
|
|
42
|
-
"@webex/common": "2.60.
|
|
43
|
-
"@webex/common-timers": "2.60.
|
|
44
|
-
"@webex/internal-plugin-device": "2.60.
|
|
45
|
-
"@webex/internal-plugin-feature": "2.60.
|
|
46
|
-
"@webex/internal-plugin-metrics": "2.60.
|
|
47
|
-
"@webex/test-helper-chai": "2.60.
|
|
48
|
-
"@webex/test-helper-mocha": "2.60.
|
|
49
|
-
"@webex/test-helper-mock-web-socket": "2.60.
|
|
50
|
-
"@webex/test-helper-mock-webex": "2.60.
|
|
51
|
-
"@webex/test-helper-refresh-callback": "2.60.
|
|
52
|
-
"@webex/test-helper-test-users": "2.60.
|
|
53
|
-
"@webex/webex-core": "2.60.
|
|
41
|
+
"@webex/common": "2.60.1-next.2",
|
|
42
|
+
"@webex/common-timers": "2.60.1-next.2",
|
|
43
|
+
"@webex/internal-plugin-device": "2.60.1-next.2",
|
|
44
|
+
"@webex/internal-plugin-feature": "2.60.1-next.2",
|
|
45
|
+
"@webex/internal-plugin-metrics": "2.60.1-next.2",
|
|
46
|
+
"@webex/test-helper-chai": "2.60.1-next.2",
|
|
47
|
+
"@webex/test-helper-mocha": "2.60.1-next.2",
|
|
48
|
+
"@webex/test-helper-mock-web-socket": "2.60.1-next.2",
|
|
49
|
+
"@webex/test-helper-mock-webex": "2.60.1-next.2",
|
|
50
|
+
"@webex/test-helper-refresh-callback": "2.60.1-next.2",
|
|
51
|
+
"@webex/test-helper-test-users": "2.60.1-next.2",
|
|
52
|
+
"@webex/webex-core": "2.60.1-next.2",
|
|
54
53
|
"backoff": "^2.5.0",
|
|
55
54
|
"lodash": "^4.17.21",
|
|
56
55
|
"uuid": "^3.3.2",
|
|
@@ -59,10 +58,12 @@
|
|
|
59
58
|
"scripts": {
|
|
60
59
|
"build": "yarn build:src",
|
|
61
60
|
"build:src": "webex-legacy-tools build -dest \"./dist\" -src \"./src\" -js -ts -maps",
|
|
61
|
+
"deploy:npm": "yarn npm publish",
|
|
62
62
|
"test": "yarn test:style && yarn test:unit && yarn test:integration && yarn test:browser",
|
|
63
63
|
"test:browser:broken": "webex-legacy-tools test --integration --unit --runner karma",
|
|
64
64
|
"test:integration:broken": "webex-legacy-tools test --integration --runner mocha",
|
|
65
65
|
"test:style": "eslint ./src/**/*.*",
|
|
66
66
|
"test:unit": "webex-legacy-tools test --unit --runner jest"
|
|
67
|
-
}
|
|
68
|
-
|
|
67
|
+
},
|
|
68
|
+
"version": "2.60.1-next.2"
|
|
69
|
+
}
|
package/src/mercury.js
CHANGED
|
@@ -49,7 +49,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
49
49
|
@oneFlight
|
|
50
50
|
connect(webSocketUrl) {
|
|
51
51
|
if (this.connected) {
|
|
52
|
-
this.logger.info(
|
|
52
|
+
this.logger.info(`${this.namespace}: already connected, will not connect again`);
|
|
53
53
|
|
|
54
54
|
return Promise.resolve();
|
|
55
55
|
}
|
|
@@ -59,7 +59,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
59
59
|
return Promise.resolve(
|
|
60
60
|
this.webex.internal.device.registered || this.webex.internal.device.register()
|
|
61
61
|
).then(() => {
|
|
62
|
-
this.logger.info(
|
|
62
|
+
this.logger.info(`${this.namespace}: connecting`);
|
|
63
63
|
|
|
64
64
|
return this._connectWithBackoff(webSocketUrl);
|
|
65
65
|
});
|
|
@@ -69,16 +69,14 @@ const Mercury = WebexPlugin.extend({
|
|
|
69
69
|
disconnect() {
|
|
70
70
|
return new Promise((resolve) => {
|
|
71
71
|
if (this.backoffCall) {
|
|
72
|
-
this.logger.info(
|
|
72
|
+
this.logger.info(`${this.namespace}: aborting connection`);
|
|
73
73
|
this.backoffCall.abort();
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
if (this.socket) {
|
|
77
77
|
this.socket.removeAllListeners('message');
|
|
78
78
|
this.once('offline', resolve);
|
|
79
|
-
this.socket.close();
|
|
80
|
-
|
|
81
|
-
return;
|
|
79
|
+
resolve(this.socket.close());
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
resolve();
|
|
@@ -165,7 +163,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
165
163
|
Promise.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()])
|
|
166
164
|
.then(([webSocketUrl, token]) => {
|
|
167
165
|
if (!this.backoffCall) {
|
|
168
|
-
const msg =
|
|
166
|
+
const msg = `${this.namespace}: prevent socket open when backoffCall no longer defined`;
|
|
169
167
|
|
|
170
168
|
this.logger.info(msg);
|
|
171
169
|
|
|
@@ -185,7 +183,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
185
183
|
|
|
186
184
|
// if the consumer has supplied request options use them
|
|
187
185
|
if (this.webex.config.defaultMercuryOptions) {
|
|
188
|
-
this.logger.info(
|
|
186
|
+
this.logger.info(`${this.namespace}: setting custom options`);
|
|
189
187
|
options = {...options, ...this.webex.config.defaultMercuryOptions};
|
|
190
188
|
}
|
|
191
189
|
|
|
@@ -193,18 +191,14 @@ const Mercury = WebexPlugin.extend({
|
|
|
193
191
|
// the socket if it is in the process of being opened.
|
|
194
192
|
this.socket = socket;
|
|
195
193
|
|
|
194
|
+
this.logger.info(`${this.namespace} connection url: ${webSocketUrl}`);
|
|
195
|
+
|
|
196
196
|
return socket.open(webSocketUrl, options);
|
|
197
197
|
})
|
|
198
198
|
.then(() => {
|
|
199
|
-
this.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
},
|
|
203
|
-
tags: {
|
|
204
|
-
action: 'connected',
|
|
205
|
-
url: attemptWSUrl,
|
|
206
|
-
},
|
|
207
|
-
});
|
|
199
|
+
this.logger.info(
|
|
200
|
+
`${this.namespace}: connected to mercury, success, action: connected, url: ${attemptWSUrl}`
|
|
201
|
+
);
|
|
208
202
|
callback();
|
|
209
203
|
|
|
210
204
|
return this.webex.internal.feature
|
|
@@ -225,19 +219,19 @@ const Mercury = WebexPlugin.extend({
|
|
|
225
219
|
if (reason.code !== 1006 && this.backoffCall && this.backoffCall.getNumRetries() > 0) {
|
|
226
220
|
this._emit('connection_failed', reason, {retries: this.backoffCall.getNumRetries()});
|
|
227
221
|
}
|
|
228
|
-
this.logger.info(
|
|
222
|
+
this.logger.info(`${this.namespace}: connection attempt failed`, reason);
|
|
229
223
|
// UnknownResponse is produced by IE for any 4XXX; treated it like a bad
|
|
230
224
|
// web socket url and let WDM handle the token checking
|
|
231
225
|
if (reason instanceof UnknownResponse) {
|
|
232
226
|
this.logger.info(
|
|
233
|
-
|
|
227
|
+
`${this.namespace}: received unknown response code, refreshing device registration`
|
|
234
228
|
);
|
|
235
229
|
|
|
236
230
|
return this.webex.internal.device.refresh().then(() => callback(reason));
|
|
237
231
|
}
|
|
238
232
|
// NotAuthorized implies expired token
|
|
239
233
|
if (reason instanceof NotAuthorized) {
|
|
240
|
-
this.logger.info(
|
|
234
|
+
this.logger.info(`${this.namespace}: received authorization error, reauthorizing`);
|
|
241
235
|
|
|
242
236
|
return this.webex.credentials.refresh({force: true}).then(() => callback(reason));
|
|
243
237
|
}
|
|
@@ -250,7 +244,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
250
244
|
// BadRequest implies current credentials are for a Service Account
|
|
251
245
|
// Forbidden implies current user is not entitle for Webex
|
|
252
246
|
if (reason instanceof BadRequest || reason instanceof Forbidden) {
|
|
253
|
-
this.logger.warn(
|
|
247
|
+
this.logger.warn(`${this.namespace}: received unrecoverable response from mercury`);
|
|
254
248
|
this.backoffCall.abort();
|
|
255
249
|
|
|
256
250
|
return callback(reason);
|
|
@@ -261,18 +255,8 @@ const Mercury = WebexPlugin.extend({
|
|
|
261
255
|
.then((haMessagingEnabled) => {
|
|
262
256
|
if (haMessagingEnabled) {
|
|
263
257
|
this.logger.info(
|
|
264
|
-
|
|
258
|
+
`${this.namespace}: received a generic connection error, will try to connect to another datacenter. failed, action: 'failed', url: ${attemptWSUrl} error: ${reason.message}`
|
|
265
259
|
);
|
|
266
|
-
this.webex.internal.metrics.submitClientMetrics('web-ha-mercury', {
|
|
267
|
-
fields: {
|
|
268
|
-
success: false,
|
|
269
|
-
},
|
|
270
|
-
tags: {
|
|
271
|
-
action: 'failed',
|
|
272
|
-
error: reason.message,
|
|
273
|
-
url: attemptWSUrl,
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
260
|
|
|
277
261
|
return this.webex.internal.services.markFailedUrl(attemptWSUrl);
|
|
278
262
|
}
|
|
@@ -285,7 +269,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
285
269
|
return callback(reason);
|
|
286
270
|
})
|
|
287
271
|
.catch((reason) => {
|
|
288
|
-
this.logger.error(
|
|
272
|
+
this.logger.error(`${this.namespace}: failed to handle connection failure`, reason);
|
|
289
273
|
callback(reason);
|
|
290
274
|
});
|
|
291
275
|
},
|
|
@@ -301,7 +285,9 @@ const Mercury = WebexPlugin.extend({
|
|
|
301
285
|
this.backoffCall = undefined;
|
|
302
286
|
if (err) {
|
|
303
287
|
this.logger.info(
|
|
304
|
-
|
|
288
|
+
`${
|
|
289
|
+
this.namespace
|
|
290
|
+
}: failed to connect after ${call.getNumRetries()} retries; log statement about next retry was inaccurate; ${err}`
|
|
305
291
|
);
|
|
306
292
|
|
|
307
293
|
return reject(err);
|
|
@@ -314,7 +300,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
314
300
|
|
|
315
301
|
// eslint-disable-next-line prefer-reflect
|
|
316
302
|
call = backoff.call((callback) => {
|
|
317
|
-
this.logger.info(
|
|
303
|
+
this.logger.info(`${this.namespace}: executing connection attempt ${call.getNumRetries()}`);
|
|
318
304
|
this._attemptConnection(webSocketUrl, callback);
|
|
319
305
|
}, onComplete);
|
|
320
306
|
|
|
@@ -330,7 +316,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
330
316
|
}
|
|
331
317
|
|
|
332
318
|
call.on('abort', () => {
|
|
333
|
-
this.logger.info(
|
|
319
|
+
this.logger.info(`${this.namespace}: connection aborted`);
|
|
334
320
|
reject(new Error('Mercury Connection Aborted'));
|
|
335
321
|
});
|
|
336
322
|
|
|
@@ -340,16 +326,16 @@ const Mercury = WebexPlugin.extend({
|
|
|
340
326
|
const delay = Math.min(call.strategy_.nextBackoffDelay_, this.config.backoffTimeMax);
|
|
341
327
|
|
|
342
328
|
this.logger.info(
|
|
343
|
-
|
|
329
|
+
`${this.namespace}: failed to connect; attempting retry ${number + 1} in ${delay} ms`
|
|
344
330
|
);
|
|
345
331
|
/* istanbul ignore if */
|
|
346
332
|
if (process.env.NODE_ENV === 'development') {
|
|
347
|
-
this.logger.debug(
|
|
333
|
+
this.logger.debug(`${this.namespace}: `, err, err.stack);
|
|
348
334
|
}
|
|
349
335
|
|
|
350
336
|
return;
|
|
351
337
|
}
|
|
352
|
-
this.logger.info(
|
|
338
|
+
this.logger.info(`${this.namespace}: connected`);
|
|
353
339
|
});
|
|
354
340
|
|
|
355
341
|
call.start();
|
|
@@ -362,7 +348,10 @@ const Mercury = WebexPlugin.extend({
|
|
|
362
348
|
try {
|
|
363
349
|
this.trigger(...args);
|
|
364
350
|
} catch (error) {
|
|
365
|
-
this.logger.error(
|
|
351
|
+
this.logger.error(`${this.namespace}: error occurred in event handler`, {
|
|
352
|
+
error,
|
|
353
|
+
arguments: args,
|
|
354
|
+
});
|
|
366
355
|
}
|
|
367
356
|
},
|
|
368
357
|
|
|
@@ -403,20 +392,20 @@ const Mercury = WebexPlugin.extend({
|
|
|
403
392
|
case 1003:
|
|
404
393
|
// metric: disconnect
|
|
405
394
|
this.logger.info(
|
|
406
|
-
|
|
395
|
+
`${this.namespace}: Mercury service rejected last message; will not reconnect: ${event.reason}`
|
|
407
396
|
);
|
|
408
397
|
this._emit('offline.permanent', event);
|
|
409
398
|
break;
|
|
410
399
|
case 4000:
|
|
411
400
|
// metric: disconnect
|
|
412
|
-
this.logger.info(
|
|
401
|
+
this.logger.info(`${this.namespace}: socket replaced; will not reconnect`);
|
|
413
402
|
this._emit('offline.replaced', event);
|
|
414
403
|
break;
|
|
415
404
|
case 1001:
|
|
416
405
|
case 1005:
|
|
417
406
|
case 1006:
|
|
418
407
|
case 1011:
|
|
419
|
-
this.logger.info(
|
|
408
|
+
this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
|
|
420
409
|
this._emit('offline.transient', event);
|
|
421
410
|
this._reconnect(socketUrl);
|
|
422
411
|
// metric: disconnect
|
|
@@ -424,23 +413,25 @@ const Mercury = WebexPlugin.extend({
|
|
|
424
413
|
break;
|
|
425
414
|
case 1000:
|
|
426
415
|
if (normalReconnectReasons.includes(reason)) {
|
|
427
|
-
this.logger.info(
|
|
416
|
+
this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
|
|
428
417
|
this._emit('offline.transient', event);
|
|
429
418
|
this._reconnect(socketUrl);
|
|
430
419
|
// metric: disconnect
|
|
431
420
|
// if (reason === done forced) metric: force closure
|
|
432
421
|
} else {
|
|
433
|
-
this.logger.info(
|
|
422
|
+
this.logger.info(`${this.namespace}: socket disconnected; will not reconnect`);
|
|
434
423
|
this._emit('offline.permanent', event);
|
|
435
424
|
}
|
|
436
425
|
break;
|
|
437
426
|
default:
|
|
438
|
-
this.logger.info(
|
|
427
|
+
this.logger.info(
|
|
428
|
+
`${this.namespace}: socket disconnected unexpectedly; will not reconnect`
|
|
429
|
+
);
|
|
439
430
|
// unexpected disconnect
|
|
440
431
|
this._emit('offline.permanent', event);
|
|
441
432
|
}
|
|
442
433
|
} catch (error) {
|
|
443
|
-
this.logger.error(
|
|
434
|
+
this.logger.error(`${this.namespace}: error occurred in close handler`, error);
|
|
444
435
|
}
|
|
445
436
|
},
|
|
446
437
|
|
|
@@ -448,7 +439,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
448
439
|
const envelope = event.data;
|
|
449
440
|
|
|
450
441
|
if (process.env.ENABLE_MERCURY_LOGGING) {
|
|
451
|
-
this.logger.debug(
|
|
442
|
+
this.logger.debug(`${this.namespace}: message envelope: `, envelope);
|
|
452
443
|
}
|
|
453
444
|
|
|
454
445
|
const {data} = envelope;
|
|
@@ -465,7 +456,7 @@ const Mercury = WebexPlugin.extend({
|
|
|
465
456
|
resolve((this.webex[namespace] || this.webex.internal[namespace])[name](data))
|
|
466
457
|
).catch((reason) =>
|
|
467
458
|
this.logger.error(
|
|
468
|
-
|
|
459
|
+
`${this.namespace}: error occurred in autowired event handler for ${data.eventType}`,
|
|
469
460
|
reason
|
|
470
461
|
)
|
|
471
462
|
);
|
|
@@ -484,12 +475,12 @@ const Mercury = WebexPlugin.extend({
|
|
|
484
475
|
}
|
|
485
476
|
})
|
|
486
477
|
.catch((reason) => {
|
|
487
|
-
this.logger.error(
|
|
478
|
+
this.logger.error(`${this.namespace}: error occurred processing socket message`, reason);
|
|
488
479
|
});
|
|
489
480
|
},
|
|
490
481
|
|
|
491
482
|
_reconnect(webSocketUrl) {
|
|
492
|
-
this.logger.info(
|
|
483
|
+
this.logger.info(`${this.namespace}: reconnecting`);
|
|
493
484
|
|
|
494
485
|
return this.connect(webSocketUrl);
|
|
495
486
|
},
|
|
@@ -30,6 +30,7 @@ export default class Socket extends EventEmitter {
|
|
|
30
30
|
*/
|
|
31
31
|
constructor() {
|
|
32
32
|
super();
|
|
33
|
+
this._domain = 'unknown-domain';
|
|
33
34
|
this.onmessage = this.onmessage.bind(this);
|
|
34
35
|
this.onclose = this.onclose.bind(this);
|
|
35
36
|
}
|
|
@@ -111,10 +112,10 @@ export default class Socket extends EventEmitter {
|
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
// logger is defined once open is called
|
|
114
|
-
this.logger.info(
|
|
115
|
+
this.logger.info(`socket,${this._domain}: closing`);
|
|
115
116
|
|
|
116
117
|
if (socket.readyState === 2 || socket.readyState === 3) {
|
|
117
|
-
this.logger.info(
|
|
118
|
+
this.logger.info(`socket,${this._domain}: already closed`);
|
|
118
119
|
resolve();
|
|
119
120
|
|
|
120
121
|
return;
|
|
@@ -134,7 +135,7 @@ export default class Socket extends EventEmitter {
|
|
|
134
135
|
|
|
135
136
|
const closeTimer = safeSetTimeout(() => {
|
|
136
137
|
try {
|
|
137
|
-
this.logger.info(
|
|
138
|
+
this.logger.info(`socket,${this._domain}: no close event received, forcing closure`);
|
|
138
139
|
resolve(
|
|
139
140
|
this.onclose({
|
|
140
141
|
code: 1000,
|
|
@@ -142,12 +143,12 @@ export default class Socket extends EventEmitter {
|
|
|
142
143
|
})
|
|
143
144
|
);
|
|
144
145
|
} catch (error) {
|
|
145
|
-
this.logger.warn(
|
|
146
|
+
this.logger.warn(`socket,${this._domain}: force-close failed`, error);
|
|
146
147
|
}
|
|
147
148
|
}, this.forceCloseDelay);
|
|
148
149
|
|
|
149
150
|
socket.onclose = (event) => {
|
|
150
|
-
this.logger.info(
|
|
151
|
+
this.logger.info(`socket,${this._domain}: close event fired`, event.code, event.reason);
|
|
151
152
|
clearTimeout(closeTimer);
|
|
152
153
|
this.onclose(event);
|
|
153
154
|
resolve(event);
|
|
@@ -171,6 +172,12 @@ export default class Socket extends EventEmitter {
|
|
|
171
172
|
* @returns {Promise}
|
|
172
173
|
*/
|
|
173
174
|
open(url, options) {
|
|
175
|
+
try {
|
|
176
|
+
this._domain = new URL(url).hostname;
|
|
177
|
+
} catch {
|
|
178
|
+
this._domain = url;
|
|
179
|
+
}
|
|
180
|
+
|
|
174
181
|
return new Promise((resolve, reject) => {
|
|
175
182
|
/* eslint complexity: [0] */
|
|
176
183
|
if (!url) {
|
|
@@ -201,7 +208,7 @@ export default class Socket extends EventEmitter {
|
|
|
201
208
|
|
|
202
209
|
const WebSocket = Socket.getWebSocketConstructor();
|
|
203
210
|
|
|
204
|
-
this.logger.info(
|
|
211
|
+
this.logger.info(`socket,${this._domain}: creating WebSocket`);
|
|
205
212
|
const socket = new WebSocket(url, [], options);
|
|
206
213
|
|
|
207
214
|
socket.binaryType = 'arraybuffer';
|
|
@@ -209,7 +216,7 @@ export default class Socket extends EventEmitter {
|
|
|
209
216
|
|
|
210
217
|
socket.onclose = (event) => {
|
|
211
218
|
event = this._fixCloseCode(event);
|
|
212
|
-
this.logger.info(
|
|
219
|
+
this.logger.info(`socket,${this._domain}: closed before open`, event.code, event.reason);
|
|
213
220
|
switch (event.code) {
|
|
214
221
|
case 1005:
|
|
215
222
|
// IE 11 doesn't seem to allow 4XXX codes, so if we get a 1005, assume
|
|
@@ -231,10 +238,10 @@ export default class Socket extends EventEmitter {
|
|
|
231
238
|
};
|
|
232
239
|
|
|
233
240
|
socket.onopen = () => {
|
|
234
|
-
this.logger.info(
|
|
241
|
+
this.logger.info(`socket,${this._domain}: connected`);
|
|
235
242
|
this._authorize()
|
|
236
243
|
.then(() => {
|
|
237
|
-
this.logger.info(
|
|
244
|
+
this.logger.info(`socket,${this._domain}: authorized`);
|
|
238
245
|
socket.onclose = this.onclose;
|
|
239
246
|
resolve();
|
|
240
247
|
})
|
|
@@ -242,11 +249,11 @@ export default class Socket extends EventEmitter {
|
|
|
242
249
|
};
|
|
243
250
|
|
|
244
251
|
socket.onerror = (event) => {
|
|
245
|
-
this.logger.warn(
|
|
252
|
+
this.logger.warn(`socket,${this._domain}: error event fired`, event);
|
|
246
253
|
};
|
|
247
254
|
|
|
248
255
|
sockets.set(this, socket);
|
|
249
|
-
this.logger.info(
|
|
256
|
+
this.logger.info(`socket,${this._domain}: waiting for server`);
|
|
250
257
|
});
|
|
251
258
|
}
|
|
252
259
|
|
|
@@ -256,7 +263,7 @@ export default class Socket extends EventEmitter {
|
|
|
256
263
|
* @returns {undefined}
|
|
257
264
|
*/
|
|
258
265
|
onclose(event) {
|
|
259
|
-
this.logger.info(
|
|
266
|
+
this.logger.info(`socket,${this._domain}: closed`, event.code, event.reason);
|
|
260
267
|
clearTimeout(this.pongTimer);
|
|
261
268
|
clearTimeout(this.pingTimer);
|
|
262
269
|
|
|
@@ -278,10 +285,10 @@ export default class Socket extends EventEmitter {
|
|
|
278
285
|
const data = JSON.parse(event.data);
|
|
279
286
|
const sequenceNumber = parseInt(data.sequenceNumber, 10);
|
|
280
287
|
|
|
281
|
-
this.logger.debug(
|
|
288
|
+
this.logger.debug(`socket,${this._domain}: sequence number: `, sequenceNumber);
|
|
282
289
|
if (this.expectedSequenceNumber && sequenceNumber !== this.expectedSequenceNumber) {
|
|
283
290
|
this.logger.debug(
|
|
284
|
-
`socket: sequence number mismatch indicates lost mercury message. expected: ${this.expectedSequenceNumber}, actual: ${sequenceNumber}`
|
|
291
|
+
`socket,${this._domain}: sequence number mismatch indicates lost mercury message. expected: ${this.expectedSequenceNumber}, actual: ${sequenceNumber}`
|
|
285
292
|
);
|
|
286
293
|
this.emit('sequence-mismatch', sequenceNumber, this.expectedSequenceNumber);
|
|
287
294
|
}
|
|
@@ -303,7 +310,7 @@ export default class Socket extends EventEmitter {
|
|
|
303
310
|
// message from Mercury. At this time, the only action we have is to
|
|
304
311
|
// ignore it and move on.
|
|
305
312
|
/* istanbul ignore next */
|
|
306
|
-
this.logger.warn(
|
|
313
|
+
this.logger.warn(`socket,${this._domain}: error while receiving WebSocket message`, error);
|
|
307
314
|
}
|
|
308
315
|
}
|
|
309
316
|
|
|
@@ -357,7 +364,7 @@ export default class Socket extends EventEmitter {
|
|
|
357
364
|
*/
|
|
358
365
|
_authorize() {
|
|
359
366
|
return new Promise((resolve) => {
|
|
360
|
-
this.logger.info(
|
|
367
|
+
this.logger.info(`socket,${this._domain}: authorizing`);
|
|
361
368
|
this.send({
|
|
362
369
|
id: uuid.v4(),
|
|
363
370
|
type: 'authorization',
|
|
@@ -395,12 +402,18 @@ export default class Socket extends EventEmitter {
|
|
|
395
402
|
if (event.code === 1005 && event.reason) {
|
|
396
403
|
switch (event.reason.toLowerCase()) {
|
|
397
404
|
case 'replaced':
|
|
398
|
-
this.logger.info(
|
|
405
|
+
this.logger.info(
|
|
406
|
+
`socket,${this._domain}: fixing CloseEvent code for reason: `,
|
|
407
|
+
event.reason
|
|
408
|
+
);
|
|
399
409
|
event.code = 4000;
|
|
400
410
|
break;
|
|
401
411
|
case 'authentication failed':
|
|
402
412
|
case 'authentication did not happen within the timeout window of 30000 seconds.':
|
|
403
|
-
this.logger.info(
|
|
413
|
+
this.logger.info(
|
|
414
|
+
`socket,${this._domain}: fixing CloseEvent code for reason: `,
|
|
415
|
+
event.reason
|
|
416
|
+
);
|
|
404
417
|
event.code = 1008;
|
|
405
418
|
break;
|
|
406
419
|
default:
|
|
@@ -420,10 +433,12 @@ export default class Socket extends EventEmitter {
|
|
|
420
433
|
_ping(id) {
|
|
421
434
|
const confirmPongId = (event) => {
|
|
422
435
|
try {
|
|
423
|
-
this.logger.debug(
|
|
436
|
+
this.logger.debug(`socket,${this._domain}: pong`, event.data.id);
|
|
424
437
|
if (event.data && event.data.id !== id) {
|
|
425
|
-
this.logger.info(
|
|
426
|
-
|
|
438
|
+
this.logger.info(
|
|
439
|
+
`socket,${this._domain}: received pong for wrong ping id, closing socket`
|
|
440
|
+
);
|
|
441
|
+
this.logger.debug(`socket,${this._domain}: expected`, id, 'received', event.data.id);
|
|
427
442
|
this.close({
|
|
428
443
|
code: 1000,
|
|
429
444
|
reason: 'Pong mismatch',
|
|
@@ -433,24 +448,29 @@ export default class Socket extends EventEmitter {
|
|
|
433
448
|
// This try/catch block was added as a debugging step; to the best of my
|
|
434
449
|
// knowledge, the above can never throw.
|
|
435
450
|
/* istanbul ignore next */
|
|
436
|
-
this.logger.error(
|
|
451
|
+
this.logger.error(`socket,${this._domain}: error occurred in confirmPongId`, error);
|
|
437
452
|
}
|
|
438
453
|
};
|
|
439
454
|
|
|
440
455
|
const onPongNotReceived = () => {
|
|
441
456
|
try {
|
|
442
|
-
this.logger.info(
|
|
457
|
+
this.logger.info(
|
|
458
|
+
`socket,${this._domain}: pong not receive in expected period, closing socket`
|
|
459
|
+
);
|
|
443
460
|
this.close({
|
|
444
461
|
code: 1000,
|
|
445
462
|
reason: 'Pong not received',
|
|
446
463
|
}).catch((reason) => {
|
|
447
|
-
this.logger.warn(
|
|
464
|
+
this.logger.warn(
|
|
465
|
+
`socket,${this._domain}: failed to close socket after missed pong`,
|
|
466
|
+
reason
|
|
467
|
+
);
|
|
448
468
|
});
|
|
449
469
|
} catch (error) {
|
|
450
470
|
// This try/catch block was added as a debugging step; to the best of my
|
|
451
471
|
// knowledge, the above can never throw.
|
|
452
472
|
/* istanbul ignore next */
|
|
453
|
-
this.logger.error(
|
|
473
|
+
this.logger.error(`socket,${this._domain}: error occurred in onPongNotReceived`, error);
|
|
454
474
|
}
|
|
455
475
|
};
|
|
456
476
|
|
|
@@ -462,7 +482,10 @@ export default class Socket extends EventEmitter {
|
|
|
462
482
|
// This try/catch block was added as a debugging step; to the best of my
|
|
463
483
|
// knowledge, the above can never throw.
|
|
464
484
|
/* istanbul ignore next */
|
|
465
|
-
this.logger.error(
|
|
485
|
+
this.logger.error(
|
|
486
|
+
`socket,${this._domain}: error occurred in scheduleNextPingAndCancelPongTimer`,
|
|
487
|
+
error
|
|
488
|
+
);
|
|
466
489
|
}
|
|
467
490
|
};
|
|
468
491
|
|
|
@@ -471,7 +494,7 @@ export default class Socket extends EventEmitter {
|
|
|
471
494
|
this.once('pong', scheduleNextPingAndCancelPongTimer);
|
|
472
495
|
this.once('pong', confirmPongId);
|
|
473
496
|
|
|
474
|
-
this.logger.debug(`socket: ping ${id}`);
|
|
497
|
+
this.logger.debug(`socket,${this._domain}: ping ${id}`);
|
|
475
498
|
|
|
476
499
|
return this.send({
|
|
477
500
|
id,
|
|
@@ -32,12 +32,13 @@ describe('plugin-mercury', function () {
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
describe('onBeforeLogout()', () => {
|
|
35
|
-
it('disconnects the web socket', () =>
|
|
35
|
+
it('disconnects the web socket', () => {
|
|
36
36
|
webex.logout({noRedirect: true}).then(() => {
|
|
37
37
|
assert.called(webex.internal.mercury.disconnect);
|
|
38
38
|
assert.isFalse(webex.internal.mercury.connected);
|
|
39
39
|
assert.called(webex.internal.device.unregister);
|
|
40
40
|
assert.isFalse(webex.internal.device.registered);
|
|
41
|
-
})
|
|
41
|
+
});
|
|
42
|
+
});
|
|
42
43
|
});
|
|
43
44
|
});
|
|
@@ -558,7 +558,7 @@ describe('plugin-mercury', () => {
|
|
|
558
558
|
return promiseTick(webex.internal.mercury.config.backoffTimeReset).then(() => {
|
|
559
559
|
assert.equal(
|
|
560
560
|
reason.message,
|
|
561
|
-
'
|
|
561
|
+
'Mercury: prevent socket open when backoffCall no longer defined'
|
|
562
562
|
);
|
|
563
563
|
});
|
|
564
564
|
});
|
|
@@ -566,12 +566,21 @@ describe('plugin-mercury', () => {
|
|
|
566
566
|
});
|
|
567
567
|
|
|
568
568
|
describe('#_emit()', () => {
|
|
569
|
-
it('emits Error-safe events', () => {
|
|
569
|
+
it('emits Error-safe events and log the error with the call parameters', () => {
|
|
570
|
+
const error = 'error';
|
|
571
|
+
const event = {data: 'some data'};
|
|
570
572
|
mercury.on('break', () => {
|
|
571
|
-
throw
|
|
573
|
+
throw error;
|
|
572
574
|
});
|
|
575
|
+
sinon.stub(mercury.logger, 'error');
|
|
573
576
|
|
|
574
|
-
return Promise.resolve(mercury._emit('break'))
|
|
577
|
+
return Promise.resolve(mercury._emit('break', event)).then((res) => {
|
|
578
|
+
assert.calledWith(mercury.logger.error, 'Mercury: error occurred in event handler', {
|
|
579
|
+
error,
|
|
580
|
+
arguments: ['break', event],
|
|
581
|
+
});
|
|
582
|
+
return res;
|
|
583
|
+
});
|
|
575
584
|
});
|
|
576
585
|
});
|
|
577
586
|
|