@webex/internal-plugin-mercury 3.0.0-beta.3 → 3.0.0-beta.300

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/src/mercury.js CHANGED
@@ -15,16 +15,11 @@ import {
15
15
  Forbidden,
16
16
  NotAuthorized,
17
17
  UnknownResponse,
18
- ConnectionError
18
+ ConnectionError,
19
19
  // NotFound
20
20
  } from './errors';
21
21
 
22
- const normalReconnectReasons = [
23
- 'idle',
24
- 'done (forced)',
25
- 'pong not received',
26
- 'pong mismatch'
27
- ];
22
+ const normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'pong mismatch'];
28
23
 
29
24
  const Mercury = WebexPlugin.extend({
30
25
  namespace: 'Mercury',
@@ -32,14 +27,14 @@ const Mercury = WebexPlugin.extend({
32
27
  session: {
33
28
  connected: {
34
29
  default: false,
35
- type: 'boolean'
30
+ type: 'boolean',
36
31
  },
37
32
  connecting: {
38
33
  default: false,
39
- type: 'boolean'
34
+ type: 'boolean',
40
35
  },
41
36
  socket: 'object',
42
- localClusterServiceUrls: 'object'
37
+ localClusterServiceUrls: 'object',
43
38
  },
44
39
 
45
40
  derived: {
@@ -47,42 +42,41 @@ const Mercury = WebexPlugin.extend({
47
42
  deps: ['connected'],
48
43
  fn() {
49
44
  return this.connected;
50
- }
51
- }
45
+ },
46
+ },
52
47
  },
53
48
 
54
49
  @oneFlight
55
50
  connect(webSocketUrl) {
56
51
  if (this.connected) {
57
- this.logger.info('mercury: already connected, will not connect again');
52
+ this.logger.info(`${this.namespace}: already connected, will not connect again`);
58
53
 
59
54
  return Promise.resolve();
60
55
  }
61
56
 
62
57
  this.connecting = true;
63
58
 
64
- return Promise.resolve(this.webex.internal.device.registered || this.webex.internal.device.register())
65
- .then(() => {
66
- this.logger.info('mercury: connecting');
59
+ return Promise.resolve(
60
+ this.webex.internal.device.registered || this.webex.internal.device.register()
61
+ ).then(() => {
62
+ this.logger.info(`${this.namespace}: connecting`);
67
63
 
68
- return this._connectWithBackoff(webSocketUrl);
69
- });
64
+ return this._connectWithBackoff(webSocketUrl);
65
+ });
70
66
  },
71
67
 
72
68
  @oneFlight
73
69
  disconnect() {
74
70
  return new Promise((resolve) => {
75
71
  if (this.backoffCall) {
76
- this.logger.info('mercury: aborting connection');
72
+ this.logger.info(`${this.namespace}: aborting connection`);
77
73
  this.backoffCall.abort();
78
74
  }
79
75
 
80
76
  if (this.socket) {
81
77
  this.socket.removeAllListeners('message');
82
78
  this.once('offline', resolve);
83
- this.socket.close();
84
-
85
- return;
79
+ resolve(this.socket.close());
86
80
  }
87
81
 
88
82
  resolve();
@@ -121,7 +115,8 @@ const Mercury = WebexPlugin.extend({
121
115
  webSocketUrl = this.webex.internal.device.webSocketUrl;
122
116
  }
123
117
 
124
- return this.webex.internal.feature.getFeature('developer', 'web-high-availability')
118
+ return this.webex.internal.feature
119
+ .getFeature('developer', 'web-high-availability')
125
120
  .then((haMessagingEnabled) => {
126
121
  if (haMessagingEnabled) {
127
122
  return this.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
@@ -138,13 +133,13 @@ const Mercury = WebexPlugin.extend({
138
133
  Object.assign(webSocketUrl.query, {
139
134
  outboundWireFormat: 'text',
140
135
  bufferStates: true,
141
- aliasHttpStatus: true
136
+ aliasHttpStatus: true,
142
137
  });
143
138
 
144
139
  if (webSharedMercury) {
145
140
  Object.assign(webSocketUrl.query, {
146
141
  mercuryRegistrationStatus: true,
147
- isRegistrationRefreshEnabled: true
142
+ isRegistrationRefreshEnabled: true,
148
143
  });
149
144
  Reflect.deleteProperty(webSocketUrl.query, 'bufferStates');
150
145
  }
@@ -168,7 +163,7 @@ const Mercury = WebexPlugin.extend({
168
163
  Promise.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()])
169
164
  .then(([webSocketUrl, token]) => {
170
165
  if (!this.backoffCall) {
171
- const msg = 'mercury: prevent socket open when backoffCall no longer defined';
166
+ const msg = `${this.namespace}: prevent socket open when backoffCall no longer defined`;
172
167
 
173
168
  this.logger.info(msg);
174
169
 
@@ -183,12 +178,12 @@ const Mercury = WebexPlugin.extend({
183
178
  pongTimeout: this.config.pongTimeout,
184
179
  token: token.toString(),
185
180
  trackingId: `${this.webex.sessionId}_${Date.now()}`,
186
- logger: this.logger
181
+ logger: this.logger,
187
182
  };
188
183
 
189
184
  // if the consumer has supplied request options use them
190
185
  if (this.webex.config.defaultMercuryOptions) {
191
- this.logger.info('mercury: setting custom options');
186
+ this.logger.info(`${this.namespace}: setting custom options`);
192
187
  options = {...options, ...this.webex.config.defaultMercuryOptions};
193
188
  }
194
189
 
@@ -196,21 +191,25 @@ const Mercury = WebexPlugin.extend({
196
191
  // the socket if it is in the process of being opened.
197
192
  this.socket = socket;
198
193
 
194
+ this.logger.info(`${this.namespace} connection url: ${webSocketUrl}`);
195
+
199
196
  return socket.open(webSocketUrl, options);
200
197
  })
201
198
  .then(() => {
202
199
  this.webex.internal.metrics.submitClientMetrics('web-ha-mercury', {
203
200
  fields: {
204
- success: true
201
+ success: true,
205
202
  },
206
203
  tags: {
204
+ namespace: this.namespace,
207
205
  action: 'connected',
208
- url: attemptWSUrl
209
- }
206
+ url: attemptWSUrl,
207
+ },
210
208
  });
211
209
  callback();
212
210
 
213
- return this.webex.internal.feature.getFeature('developer', 'web-high-availability')
211
+ return this.webex.internal.feature
212
+ .getFeature('developer', 'web-high-availability')
214
213
  .then((haMessagingEnabled) => {
215
214
  if (haMessagingEnabled) {
216
215
  return this.webex.internal.device.refresh();
@@ -227,21 +226,21 @@ const Mercury = WebexPlugin.extend({
227
226
  if (reason.code !== 1006 && this.backoffCall && this.backoffCall.getNumRetries() > 0) {
228
227
  this._emit('connection_failed', reason, {retries: this.backoffCall.getNumRetries()});
229
228
  }
230
- this.logger.info('mercury: connection attempt failed', reason);
229
+ this.logger.info(`${this.namespace}: connection attempt failed`, reason);
231
230
  // UnknownResponse is produced by IE for any 4XXX; treated it like a bad
232
231
  // web socket url and let WDM handle the token checking
233
232
  if (reason instanceof UnknownResponse) {
234
- this.logger.info('mercury: received unknown response code, refreshing device registration');
233
+ this.logger.info(
234
+ `${this.namespace}: received unknown response code, refreshing device registration`
235
+ );
235
236
 
236
- return this.webex.internal.device.refresh()
237
- .then(() => callback(reason));
237
+ return this.webex.internal.device.refresh().then(() => callback(reason));
238
238
  }
239
239
  // NotAuthorized implies expired token
240
240
  if (reason instanceof NotAuthorized) {
241
- this.logger.info('mercury: received authorization error, reauthorizing');
241
+ this.logger.info(`${this.namespace}: received authorization error, reauthorizing`);
242
242
 
243
- return this.webex.credentials.refresh({force: true})
244
- .then(() => callback(reason));
243
+ return this.webex.credentials.refresh({force: true}).then(() => callback(reason));
245
244
  }
246
245
  // // NotFound implies expired web socket url
247
246
  // else if (reason instanceof NotFound) {
@@ -252,25 +251,29 @@ const Mercury = WebexPlugin.extend({
252
251
  // BadRequest implies current credentials are for a Service Account
253
252
  // Forbidden implies current user is not entitle for Webex
254
253
  if (reason instanceof BadRequest || reason instanceof Forbidden) {
255
- this.logger.warn('mercury: received unrecoverable response from mercury');
254
+ this.logger.warn(`${this.namespace}: received unrecoverable response from mercury`);
256
255
  this.backoffCall.abort();
257
256
 
258
257
  return callback(reason);
259
258
  }
260
259
  if (reason instanceof ConnectionError) {
261
- return this.webex.internal.feature.getFeature('developer', 'web-high-availability')
260
+ return this.webex.internal.feature
261
+ .getFeature('developer', 'web-high-availability')
262
262
  .then((haMessagingEnabled) => {
263
263
  if (haMessagingEnabled) {
264
- this.logger.info('mercury: received a generic connection error, will try to connect to another datacenter');
264
+ this.logger.info(
265
+ `${this.namespace}: received a generic connection error, will try to connect to another datacenter`
266
+ );
265
267
  this.webex.internal.metrics.submitClientMetrics('web-ha-mercury', {
266
268
  fields: {
267
- success: false
269
+ success: false,
268
270
  },
269
271
  tags: {
272
+ namespace: this.namespace,
270
273
  action: 'failed',
271
274
  error: reason.message,
272
- url: attemptWSUrl
273
- }
275
+ url: attemptWSUrl,
276
+ },
274
277
  });
275
278
 
276
279
  return this.webex.internal.services.markFailedUrl(attemptWSUrl);
@@ -284,7 +287,7 @@ const Mercury = WebexPlugin.extend({
284
287
  return callback(reason);
285
288
  })
286
289
  .catch((reason) => {
287
- this.logger.error('mercury: failed to handle connection failure', reason);
290
+ this.logger.error(`${this.namespace}: failed to handle connection failure`, reason);
288
291
  callback(reason);
289
292
  });
290
293
  },
@@ -299,7 +302,11 @@ const Mercury = WebexPlugin.extend({
299
302
 
300
303
  this.backoffCall = undefined;
301
304
  if (err) {
302
- this.logger.info(`mercury: failed to connect after ${call.getNumRetries()} retries; log statement about next retry was inaccurate; ${err}`);
305
+ this.logger.info(
306
+ `${
307
+ this.namespace
308
+ }: failed to connect after ${call.getNumRetries()} retries; log statement about next retry was inaccurate; ${err}`
309
+ );
303
310
 
304
311
  return reject(err);
305
312
  }
@@ -311,21 +318,23 @@ const Mercury = WebexPlugin.extend({
311
318
 
312
319
  // eslint-disable-next-line prefer-reflect
313
320
  call = backoff.call((callback) => {
314
- this.logger.info(`mercury: executing connection attempt ${call.getNumRetries()}`);
321
+ this.logger.info(`${this.namespace}: executing connection attempt ${call.getNumRetries()}`);
315
322
  this._attemptConnection(webSocketUrl, callback);
316
323
  }, onComplete);
317
324
 
318
- call.setStrategy(new backoff.ExponentialStrategy({
319
- initialDelay: this.config.backoffTimeReset,
320
- maxDelay: this.config.backoffTimeMax
321
- }));
325
+ call.setStrategy(
326
+ new backoff.ExponentialStrategy({
327
+ initialDelay: this.config.backoffTimeReset,
328
+ maxDelay: this.config.backoffTimeMax,
329
+ })
330
+ );
322
331
 
323
332
  if (this.config.maxRetries) {
324
333
  call.failAfter(this.config.maxRetries);
325
334
  }
326
335
 
327
336
  call.on('abort', () => {
328
- this.logger.info('mercury: connection aborted');
337
+ this.logger.info(`${this.namespace}: connection aborted`);
329
338
  reject(new Error('Mercury Connection Aborted'));
330
339
  });
331
340
 
@@ -334,15 +343,17 @@ const Mercury = WebexPlugin.extend({
334
343
  const number = call.getNumRetries();
335
344
  const delay = Math.min(call.strategy_.nextBackoffDelay_, this.config.backoffTimeMax);
336
345
 
337
- this.logger.info(`mercury: failed to connect; attempting retry ${number + 1} in ${delay} ms`);
346
+ this.logger.info(
347
+ `${this.namespace}: failed to connect; attempting retry ${number + 1} in ${delay} ms`
348
+ );
338
349
  /* istanbul ignore if */
339
350
  if (process.env.NODE_ENV === 'development') {
340
- this.logger.debug('mercury: ', err, err.stack);
351
+ this.logger.debug(`${this.namespace}: `, err, err.stack);
341
352
  }
342
353
 
343
354
  return;
344
355
  }
345
- this.logger.info('mercury: connected');
356
+ this.logger.info(`${this.namespace}: connected`);
346
357
  });
347
358
 
348
359
  call.start();
@@ -354,9 +365,11 @@ const Mercury = WebexPlugin.extend({
354
365
  _emit(...args) {
355
366
  try {
356
367
  this.trigger(...args);
357
- }
358
- catch (error) {
359
- this.logger.error('mercury: error occurred in event handler', error);
368
+ } catch (error) {
369
+ this.logger.error(`${this.namespace}: error occurred in event handler`, {
370
+ error,
371
+ arguments: args,
372
+ });
360
373
  }
361
374
  },
362
375
 
@@ -373,7 +386,7 @@ const Mercury = WebexPlugin.extend({
373
386
  if ((this.webex[namespace] || this.webex.internal[namespace])[handlerName]) {
374
387
  handlers.push({
375
388
  name: handlerName,
376
- namespace
389
+ namespace,
377
390
  });
378
391
  }
379
392
 
@@ -395,20 +408,22 @@ const Mercury = WebexPlugin.extend({
395
408
 
396
409
  switch (event.code) {
397
410
  case 1003:
398
- // metric: disconnect
399
- this.logger.info(`mercury: Mercury service rejected last message; will not reconnect: ${event.reason}`);
411
+ // metric: disconnect
412
+ this.logger.info(
413
+ `${this.namespace}: Mercury service rejected last message; will not reconnect: ${event.reason}`
414
+ );
400
415
  this._emit('offline.permanent', event);
401
416
  break;
402
417
  case 4000:
403
418
  // metric: disconnect
404
- this.logger.info('mercury: socket replaced; will not reconnect');
419
+ this.logger.info(`${this.namespace}: socket replaced; will not reconnect`);
405
420
  this._emit('offline.replaced', event);
406
421
  break;
407
422
  case 1001:
408
423
  case 1005:
409
424
  case 1006:
410
425
  case 1011:
411
- this.logger.info('mercury: socket disconnected; reconnecting');
426
+ this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
412
427
  this._emit('offline.transient', event);
413
428
  this._reconnect(socketUrl);
414
429
  // metric: disconnect
@@ -416,25 +431,25 @@ const Mercury = WebexPlugin.extend({
416
431
  break;
417
432
  case 1000:
418
433
  if (normalReconnectReasons.includes(reason)) {
419
- this.logger.info('mercury: socket disconnected; reconnecting');
434
+ this.logger.info(`${this.namespace}: socket disconnected; reconnecting`);
420
435
  this._emit('offline.transient', event);
421
436
  this._reconnect(socketUrl);
422
437
  // metric: disconnect
423
438
  // if (reason === done forced) metric: force closure
424
- }
425
- else {
426
- this.logger.info('mercury: socket disconnected; will not reconnect');
439
+ } else {
440
+ this.logger.info(`${this.namespace}: socket disconnected; will not reconnect`);
427
441
  this._emit('offline.permanent', event);
428
442
  }
429
443
  break;
430
444
  default:
431
- this.logger.info('mercury: socket disconnected unexpectedly; will not reconnect');
445
+ this.logger.info(
446
+ `${this.namespace}: socket disconnected unexpectedly; will not reconnect`
447
+ );
432
448
  // unexpected disconnect
433
449
  this._emit('offline.permanent', event);
434
450
  }
435
- }
436
- catch (error) {
437
- this.logger.error('mercury: error occurred in close handler', error);
451
+ } catch (error) {
452
+ this.logger.error(`${this.namespace}: error occurred in close handler`, error);
438
453
  }
439
454
  },
440
455
 
@@ -442,7 +457,7 @@ const Mercury = WebexPlugin.extend({
442
457
  const envelope = event.data;
443
458
 
444
459
  if (process.env.ENABLE_MERCURY_LOGGING) {
445
- this.logger.debug('mercury: message envelope: ', envelope);
460
+ this.logger.debug(`${this.namespace}: message envelope: `, envelope);
446
461
  }
447
462
 
448
463
  const {data} = envelope;
@@ -450,34 +465,43 @@ const Mercury = WebexPlugin.extend({
450
465
  this._applyOverrides(data);
451
466
 
452
467
  return this._getEventHandlers(data.eventType)
453
- .reduce((promise, handler) => promise.then(() => {
454
- const {namespace, name} = handler;
455
-
456
- return new Promise((resolve) => resolve((this.webex[namespace] || this.webex.internal[namespace])[name](data)))
457
- .catch((reason) => this.logger.error(`mercury: error occurred in autowired event handler for ${data.eventType}`, reason));
458
- }), Promise.resolve())
468
+ .reduce(
469
+ (promise, handler) =>
470
+ promise.then(() => {
471
+ const {namespace, name} = handler;
472
+
473
+ return new Promise((resolve) =>
474
+ resolve((this.webex[namespace] || this.webex.internal[namespace])[name](data))
475
+ ).catch((reason) =>
476
+ this.logger.error(
477
+ `${this.namespace}: error occurred in autowired event handler for ${data.eventType}`,
478
+ reason
479
+ )
480
+ );
481
+ }),
482
+ Promise.resolve()
483
+ )
459
484
  .then(() => {
460
485
  this._emit('event', event.data);
461
486
  const [namespace] = data.eventType.split('.');
462
487
 
463
488
  if (namespace === data.eventType) {
464
489
  this._emit(`event:${namespace}`, envelope);
465
- }
466
- else {
490
+ } else {
467
491
  this._emit(`event:${namespace}`, envelope);
468
492
  this._emit(`event:${data.eventType}`, envelope);
469
493
  }
470
494
  })
471
495
  .catch((reason) => {
472
- this.logger.error('mercury: error occurred processing socket message', reason);
496
+ this.logger.error(`${this.namespace}: error occurred processing socket message`, reason);
473
497
  });
474
498
  },
475
499
 
476
500
  _reconnect(webSocketUrl) {
477
- this.logger.info('mercury: reconnecting');
501
+ this.logger.info(`${this.namespace}: reconnecting`);
478
502
 
479
503
  return this.connect(webSocketUrl);
480
- }
504
+ },
481
505
  });
482
506
 
483
507
  export default Mercury;