@webex/calling 3.12.0-mobius-socket.17 → 3.12.0-mobius-socket.19

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.
Files changed (49) hide show
  1. package/dist/CallingClient/utils/request.js +6 -3
  2. package/dist/CallingClient/utils/request.js.map +1 -1
  3. package/dist/CallingClient/utils/request.test.js +2 -2
  4. package/dist/CallingClient/utils/request.test.js.map +1 -1
  5. package/dist/CallingClient/utils/types.js.map +1 -1
  6. package/dist/SDKConnector/types.js.map +1 -1
  7. package/dist/mobius-socket/config.js +7 -44
  8. package/dist/mobius-socket/config.js.map +1 -1
  9. package/dist/mobius-socket/errors.js +25 -21
  10. package/dist/mobius-socket/errors.js.map +1 -1
  11. package/dist/mobius-socket/index.js +0 -44
  12. package/dist/mobius-socket/index.js.map +1 -1
  13. package/dist/mobius-socket/mobius-socket-events.test.js +20 -48
  14. package/dist/mobius-socket/mobius-socket-events.test.js.map +1 -1
  15. package/dist/mobius-socket/mobius-socket.js +302 -701
  16. package/dist/mobius-socket/mobius-socket.js.map +1 -1
  17. package/dist/mobius-socket/mobius-socket.test.js +435 -718
  18. package/dist/mobius-socket/mobius-socket.test.js.map +1 -1
  19. package/dist/mobius-socket/socket/socket-base.js +70 -78
  20. package/dist/mobius-socket/socket/socket-base.js.map +1 -1
  21. package/dist/mobius-socket/socket.test.js +36 -61
  22. package/dist/mobius-socket/socket.test.js.map +1 -1
  23. package/dist/mobius-socket/types.js +7 -0
  24. package/dist/mobius-socket/types.js.map +1 -0
  25. package/dist/module/CallingClient/utils/request.js +3 -2
  26. package/dist/module/mobius-socket/config.js +7 -10
  27. package/dist/module/mobius-socket/errors.js +17 -0
  28. package/dist/module/mobius-socket/index.js +0 -3
  29. package/dist/module/mobius-socket/mobius-socket.js +211 -401
  30. package/dist/module/mobius-socket/socket/socket-base.js +64 -69
  31. package/dist/module/mobius-socket/types.js +1 -0
  32. package/dist/types/CallingClient/utils/request.d.ts.map +1 -1
  33. package/dist/types/CallingClient/utils/types.d.ts +1 -1
  34. package/dist/types/CallingClient/utils/types.d.ts.map +1 -1
  35. package/dist/types/SDKConnector/types.d.ts +15 -0
  36. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  37. package/dist/types/mobius-socket/config.d.ts +7 -8
  38. package/dist/types/mobius-socket/config.d.ts.map +1 -1
  39. package/dist/types/mobius-socket/errors.d.ts +7 -0
  40. package/dist/types/mobius-socket/errors.d.ts.map +1 -1
  41. package/dist/types/mobius-socket/index.d.ts +3 -5
  42. package/dist/types/mobius-socket/index.d.ts.map +1 -1
  43. package/dist/types/mobius-socket/mobius-socket.d.ts +26 -37
  44. package/dist/types/mobius-socket/mobius-socket.d.ts.map +1 -1
  45. package/dist/types/mobius-socket/socket/socket-base.d.ts +10 -10
  46. package/dist/types/mobius-socket/socket/socket-base.d.ts.map +1 -1
  47. package/dist/types/mobius-socket/types.d.ts +21 -0
  48. package/dist/types/mobius-socket/types.d.ts.map +1 -0
  49. package/package.json +1 -1
@@ -2,18 +2,13 @@
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file
3
3
  */
4
4
  import { EventEmitter } from 'events';
5
- import { camelCase, set } from 'lodash';
6
5
  import backoff from 'backoff';
7
6
  import Socket from './socket';
8
- import { BadRequest, Forbidden, NotAuthorized, UnknownResponse, } from './errors';
7
+ import { BadRequest, Forbidden, NotAuthorized, UnknownResponse } from './errors';
9
8
  const normalReconnectReasons = ['idle', 'done (forced)'];
10
- const DEFAULT_MOBIUS_WEBSOCKET_SESSION = 'mobius-websocket-session';
11
9
  const MOBIUS_SOCKET_NAMESPACE = 'MobiusSocket';
12
10
  const TOKEN_REFRESH_INTERVAL_MS = 1 * 60 * 60 * 1000;
13
11
  function normalizeMobiusAuthToken(token) {
14
- if (typeof token !== 'string') {
15
- return token;
16
- }
17
12
  return token.replace(/^Bearer\s+/i, '');
18
13
  }
19
14
  class MobiusSocket extends EventEmitter {
@@ -25,20 +20,16 @@ class MobiusSocket extends EventEmitter {
25
20
  this.webex = webex;
26
21
  this.config = config;
27
22
  this.logger = webex.logger || console;
28
- this.defaultSessionId = DEFAULT_MOBIUS_WEBSOCKET_SESSION;
29
23
  this.connected = false;
30
24
  this.connecting = false;
31
25
  this.hasEverConnected = false;
32
26
  this.socket = undefined;
33
- this.sockets = new Map();
34
- this.backoffCalls = new Map();
35
- this._shutdownSwitchoverBackoffCalls = new Map();
36
- this._seenAsyncEventIdsBySession = new Map();
37
- this._connectPromises = new Map();
38
- this.mercuryTimeOffset = undefined;
39
- this._tokenRefreshTimer = undefined;
40
- this._tokenRefreshInFlight = undefined;
41
- this._bindInternalEvents();
27
+ this.backoffCall = undefined;
28
+ this.shutdownSwitchoverBackoffCall = undefined;
29
+ this.seenAsyncEventIds = new Map();
30
+ this.connectPromise = undefined;
31
+ this.tokenRefreshTimer = undefined;
32
+ this.tokenRefreshInFlight = undefined;
42
33
  }
43
34
  off(eventName, listener) {
44
35
  if (listener) {
@@ -47,88 +38,49 @@ class MobiusSocket extends EventEmitter {
47
38
  this.removeAllListeners(eventName);
48
39
  return this;
49
40
  }
50
- _bindInternalEvents() {
51
- this.on('event:featureToggle_update', (envelope) => {
52
- if (envelope && envelope.data) {
53
- this.webex.internal.feature.updateFeature(envelope.data.featureToggle);
54
- }
55
- });
56
- this.on('event:ActiveClusterStatusEvent', (envelope) => {
57
- if (typeof this.webex.internal.services?.switchActiveClusterIds === 'function' &&
58
- envelope &&
59
- envelope.data) {
60
- this.webex.internal.services.switchActiveClusterIds(envelope.data?.activeClusters);
61
- }
62
- });
63
- this.on('event:u2c.cache-invalidation', (envelope) => {
64
- if (typeof this.webex.internal.services?.invalidateCache === 'function' &&
65
- envelope &&
66
- envelope.data) {
67
- this.webex.internal.services.invalidateCache(envelope.data?.timestamp);
68
- }
69
- });
70
- }
71
- _attachSocketEventListeners(socket, sessionId) {
72
- socket.on('close', (event) => this._onclose(sessionId, event, socket));
73
- socket.on('message', (...args) => this._onmessage(sessionId, ...args));
74
- socket.on('pong', (...args) => this._setTimeOffset(sessionId, ...args));
75
- socket.on('sequence-mismatch', (...args) => this._emit(sessionId, 'sequence-mismatch', ...args));
76
- socket.on('ping-pong-latency', (...args) => this._emit(sessionId, 'ping-pong-latency', ...args));
41
+ attachSocketEventListeners(socket) {
42
+ socket.on('close', (event) => this.onclose(event, socket));
43
+ socket.on('message', (...args) => this.onmessage(...args));
77
44
  }
78
- _getSeenAsyncEventIds(sessionId) {
79
- let seenAsyncEventIds = this._seenAsyncEventIdsBySession.get(sessionId);
80
- if (!seenAsyncEventIds) {
81
- seenAsyncEventIds = new Map();
82
- this._seenAsyncEventIdsBySession.set(sessionId, seenAsyncEventIds);
83
- }
84
- return seenAsyncEventIds;
85
- }
86
- _clearSeenAsyncEventIds(sessionId) {
87
- if (sessionId) {
88
- this._seenAsyncEventIdsBySession.delete(sessionId);
89
- return;
90
- }
91
- this._seenAsyncEventIdsBySession.clear();
92
- }
93
- _trackAsyncEventAndShouldSuppressDuplicate(sessionId, envelope) {
45
+ trackAsyncEventAndShouldSuppressDuplicate(envelope) {
94
46
  if (envelope?.type !== 'async_event' || !envelope.eventId) {
95
47
  return false;
96
48
  }
97
- const seenAsyncEventIds = this._getSeenAsyncEventIds(sessionId);
98
- if (seenAsyncEventIds.has(envelope.eventId)) {
99
- const previousValue = seenAsyncEventIds.get(envelope.eventId);
100
- seenAsyncEventIds.delete(envelope.eventId);
101
- seenAsyncEventIds.set(envelope.eventId, previousValue);
102
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: duplicate async_event suppressed for ${sessionId}, eventId=${envelope.eventId}`);
49
+ if (this.seenAsyncEventIds.has(envelope.eventId)) {
50
+ const previousValue = this.seenAsyncEventIds.get(envelope.eventId);
51
+ this.seenAsyncEventIds.delete(envelope.eventId);
52
+ this.seenAsyncEventIds.set(envelope.eventId, previousValue);
53
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: duplicate async_event suppressed, eventId=${envelope.eventId}`);
103
54
  return true;
104
55
  }
105
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: tracking async_event for ${sessionId}, eventId=${envelope.eventId}`);
106
- seenAsyncEventIds.set(envelope.eventId, true);
107
- if (seenAsyncEventIds.size > this.config.dedupCacheMaxSize) {
108
- const oldestEventId = seenAsyncEventIds.keys().next().value;
109
- seenAsyncEventIds.delete(oldestEventId);
110
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: evicted oldest async_event from dedup cache for ${sessionId}, eventId=${oldestEventId}`);
56
+ this.logger.log(`${MOBIUS_SOCKET_NAMESPACE}: tracking async_event, eventId=${envelope.eventId}`);
57
+ this.seenAsyncEventIds.set(envelope.eventId, true);
58
+ if (this.seenAsyncEventIds.size > this.config.dedupCacheMaxSize) {
59
+ const oldestEventId = this.seenAsyncEventIds.keys().next().value;
60
+ this.seenAsyncEventIds.delete(oldestEventId);
61
+ this.logger.log(`${MOBIUS_SOCKET_NAMESPACE}: evicted oldest async_event from dedup cache, eventId=${oldestEventId}`);
111
62
  }
112
63
  return false;
113
64
  }
114
- _handleImminentShutdown(sessionId) {
115
- const oldSocket = this.sockets.get(sessionId);
65
+ handleImminentShutdown() {
66
+ const oldSocket = this.socket;
116
67
  try {
117
- if (this._shutdownSwitchoverBackoffCalls.get(sessionId)) {
118
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover already in progress for ${sessionId}`);
68
+ if (this.shutdownSwitchoverBackoffCall) {
69
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover already in progress`);
119
70
  return;
120
71
  }
121
- const switchoverId = `${Date.now()}`;
122
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover start, id=${switchoverId} for ${sessionId}`);
123
- this._connectWithBackoff(undefined, sessionId, {
72
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover start`);
73
+ this.connectWithBackoff(undefined, {
124
74
  isShutdownSwitchover: true,
125
75
  attemptOptions: {
126
76
  isShutdownSwitchover: true,
127
77
  onSuccess: (newSocket, webSocketUrl) => {
128
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover connected, url: ${webSocketUrl} for ${sessionId}`);
129
- this.socket = this.sockets.get(this.defaultSessionId);
130
- this.connected = this.hasConnectedSockets();
131
- this._emit(sessionId, 'event:mercury_shutdown_switchover_complete', {
78
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover connected, url: ${webSocketUrl}`);
79
+ newSocket.connecting = false;
80
+ newSocket.connected = true;
81
+ this.socket = newSocket;
82
+ this.connected = true;
83
+ this.emitEvent('event:mobius_shutdown_switchover_complete', {
132
84
  url: webSocketUrl,
133
85
  });
134
86
  if (oldSocket) {
@@ -138,185 +90,111 @@ class MobiusSocket extends EventEmitter {
138
90
  },
139
91
  })
140
92
  .then(() => {
141
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover completed successfully for ${sessionId}`);
93
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover completed successfully`);
142
94
  })
143
95
  .catch((err) => {
144
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover exhausted retries; will fall back to normal reconnection for ${sessionId}: `, err);
145
- this._emit(sessionId, 'event:mercury_shutdown_switchover_failed', { reason: err });
96
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover exhausted retries; will fall back to normal reconnection: `, err);
97
+ this.emitEvent('event:mobius_shutdown_switchover_failed', { reason: err });
146
98
  });
147
99
  }
148
100
  catch (e) {
149
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] error during switchover for ${sessionId}`, e);
150
- this._shutdownSwitchoverBackoffCalls.delete(sessionId);
151
- this._emit(sessionId, 'event:mercury_shutdown_switchover_failed', { reason: e });
101
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] error during switchover`, e);
102
+ this.shutdownSwitchoverBackoffCall = undefined;
103
+ this.emitEvent('event:mobius_shutdown_switchover_failed', { reason: e });
152
104
  }
153
105
  }
154
- getLastError() {
155
- return this.lastError;
156
- }
157
- getSockets() {
158
- return this.sockets;
159
- }
160
- getSocket(sessionId = this.defaultSessionId) {
161
- return this.sockets.get(sessionId);
162
- }
163
- getConnectedWebSocketUrl(sessionId = this.defaultSessionId) {
164
- const socket = this.getSocket(sessionId);
165
- if (!socket?.connected) {
106
+ getConnectedWebSocketUrl() {
107
+ if (!this.socket?.connected) {
166
108
  return undefined;
167
109
  }
168
- return socket.url;
169
- }
170
- send(payload, sessionId = this.defaultSessionId) {
171
- const socket = this.getSocket(sessionId);
172
- if (!socket || !socket.connected) {
173
- return Promise.reject(new Error(`Mobius socket is not connected for session ${sessionId}`));
174
- }
175
- return socket.send(payload);
110
+ return this.socket.url;
176
111
  }
177
- sendWssRequest(payload, sessionIdOrOptions = this.defaultSessionId, options = {}) {
112
+ sendWssRequest(payload, options = {}) {
178
113
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
179
114
  return Promise.reject(new Error('`payload` is required'));
180
115
  }
181
- let sessionId = this.defaultSessionId;
182
- let requestOptions = options;
183
- if (typeof sessionIdOrOptions === 'string') {
184
- sessionId = sessionIdOrOptions;
185
- }
186
- else if (sessionIdOrOptions && typeof sessionIdOrOptions === 'object') {
187
- requestOptions = sessionIdOrOptions;
116
+ if (!this.socket || !this.socket.connected) {
117
+ return Promise.reject(new Error('Mobius socket is not connected'));
188
118
  }
189
- const socket = this.getSocket(sessionId);
190
- if (!socket || !socket.connected) {
191
- return Promise.reject(new Error(`Mobius socket is not connected for session ${sessionId}`));
192
- }
193
- return socket.sendRequest(payload, {
194
- timeout: requestOptions.timeout,
119
+ const requestConfigOptions = {
120
+ timeout: options.timeout,
195
121
  matchesResponse: (response, request) => response?.type === 'response_event' &&
196
122
  response?.subtype === request.type &&
197
123
  response?.trackingId === request.trackingId,
198
124
  getStatusCode: (response) => response?.statusCode,
199
125
  getStatusMessage: (response) => response?.statusMessage,
200
- createError: (response, statusCode, statusMessage) => this._createWssResponseError(response, statusCode, statusMessage),
201
- createTimeoutError: (request) => this._createWssResponseError({
126
+ createError: (response, statusCode, statusMessage) => this.createWssResponseError(response, statusCode, statusMessage),
127
+ createTimeoutError: (request) => this.createWssResponseError({
202
128
  type: 'response_event',
203
129
  subtype: request.type,
204
130
  trackingId: request.trackingId,
205
131
  }, 408, 'Mobius websocket response timed out'),
206
- });
132
+ };
133
+ return this.socket.sendRequest(payload, requestConfigOptions);
207
134
  }
208
135
  isConnected() {
209
136
  return this.connected;
210
137
  }
211
- hasConnectedSockets(sessionId) {
212
- if (sessionId) {
213
- return Boolean(this.sockets.get(sessionId)?.connected);
214
- }
215
- for (const socket of this.sockets.values()) {
216
- if (socket?.connected) {
217
- return true;
218
- }
138
+ connect(webSocketUrl) {
139
+ if (this.connectPromise) {
140
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connection already in progress, returning existing promise`);
141
+ return this.connectPromise;
219
142
  }
220
- return false;
221
- }
222
- hasConnectingSockets(sessionId = this.defaultSessionId) {
223
- const socket = this.sockets.get(sessionId || this.defaultSessionId);
224
- return Boolean(socket?.connecting);
225
- }
226
- connect(webSocketUrl, sessionId = this.defaultSessionId) {
227
- if (this._connectPromises.has(sessionId)) {
228
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connection ${sessionId} already in progress, returning existing promise`);
229
- return this._connectPromises.get(sessionId);
230
- }
231
- const sessionSocket = this.sockets.get(sessionId);
232
- if (sessionSocket?.connected || sessionSocket?.connecting) {
233
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connection ${sessionId} already connected, will not connect again`);
143
+ if (this.socket?.connected || this.socket?.connecting) {
144
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: already connected, will not connect again`);
234
145
  return Promise.resolve();
235
146
  }
236
147
  if (webSocketUrl && this.socketUrl && webSocketUrl !== this.socketUrl) {
237
148
  this.hasEverConnected = false;
238
149
  }
239
- const resolvedUrl = webSocketUrl || this.socketUrl;
240
150
  if (webSocketUrl) {
241
151
  this.socketUrl = webSocketUrl;
242
152
  }
243
153
  this.connecting = true;
244
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: starting connection attempt for ${sessionId}${Number(this.config.initialConnectionMaxRetries) === 0 && !this.hasEverConnected
154
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: starting connection attempt${Number(this.config.initialConnectionMaxRetries) === 0 && !this.hasEverConnected
245
155
  ? ' (initial retries disabled)'
246
156
  : ''}`);
247
157
  const connectPromise = Promise.resolve(this.webex.internal.device.registered || this.webex.internal.device.register())
248
158
  .then(() => {
249
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connecting ${sessionId}`);
250
- return this._connectWithBackoff(resolvedUrl, sessionId);
159
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connecting`);
160
+ return this.connectWithBackoff(this.socketUrl);
251
161
  })
252
162
  .finally(() => {
253
- this._connectPromises.delete(sessionId);
163
+ this.connectPromise = undefined;
254
164
  });
255
- this._connectPromises.set(sessionId, connectPromise);
165
+ this.connectPromise = connectPromise;
256
166
  return connectPromise;
257
167
  }
258
- logout() {
259
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: logout() called`);
260
- return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason &&
261
- !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason)
262
- ? { code: 3050, reason: this.config.beforeLogoutOptionsCloseReason }
263
- : undefined);
264
- }
265
- disconnect(options, sessionId = this.defaultSessionId) {
266
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}#disconnect: connecting state: ${this.connecting}, connected state: ${this.connected}, socket exists: ${!!this
267
- .socket}, options: ${JSON.stringify(options)}`);
268
- const backoffCall = this.backoffCalls.get(sessionId);
269
- if (backoffCall) {
270
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: aborting connection ${sessionId}`);
271
- backoffCall.abort();
272
- this.backoffCalls.delete(sessionId);
273
- }
274
- const shutdownSwitchoverBackoffCall = this._shutdownSwitchoverBackoffCalls.get(sessionId);
275
- if (shutdownSwitchoverBackoffCall) {
276
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: aborting shutdown switchover connection ${sessionId}`);
277
- shutdownSwitchoverBackoffCall.abort();
278
- this._shutdownSwitchoverBackoffCalls.delete(sessionId);
279
- }
280
- this._connectPromises.delete(sessionId);
281
- const sessionSocket = this.sockets.get(sessionId);
282
- this._clearSeenAsyncEventIds(sessionId);
283
- if (!sessionSocket) {
284
- this.connected = this.hasConnectedSockets();
285
- if (!this.hasConnectedSockets()) {
286
- this._stopTokenRefreshTimer();
287
- }
168
+ disconnect(options) {
169
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}#disconnect: connecting state: ${this.connecting},
170
+ connected state: ${this.connected}, socket exists: ${!!this.socket},
171
+ options: ${JSON.stringify(options)}`);
172
+ if (this.backoffCall) {
173
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: aborting connection`);
174
+ this.backoffCall.abort();
175
+ this.backoffCall = undefined;
176
+ }
177
+ if (this.shutdownSwitchoverBackoffCall) {
178
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: aborting shutdown switchover connection`);
179
+ this.shutdownSwitchoverBackoffCall.abort();
180
+ this.shutdownSwitchoverBackoffCall = undefined;
181
+ }
182
+ this.connectPromise = undefined;
183
+ this.seenAsyncEventIds.clear();
184
+ if (!this.socket) {
185
+ this.connected = false;
186
+ this.stopTokenRefreshTimer();
288
187
  return Promise.resolve();
289
188
  }
290
- sessionSocket.removeAllListeners('message');
291
- sessionSocket.connecting = false;
292
- sessionSocket.connected = false;
293
- return Promise.resolve(sessionSocket.close(options || undefined)).finally(() => {
294
- this.connected = this.hasConnectedSockets();
295
- if (!this.hasConnectedSockets()) {
296
- this._stopTokenRefreshTimer();
297
- }
298
- });
299
- }
300
- disconnectAll(options) {
301
- const disconnectPromises = [];
302
- for (const sessionId of this.sockets.keys()) {
303
- disconnectPromises.push(this.disconnect(options, sessionId));
304
- }
305
- return Promise.all(disconnectPromises).then(() => {
189
+ this.socket.removeAllListeners('message');
190
+ this.socket.connecting = false;
191
+ this.socket.connected = false;
192
+ return Promise.resolve(this.socket.close(options || undefined)).finally(() => {
306
193
  this.connected = false;
307
- this.socket = undefined;
308
- this.sockets.clear();
309
- this.backoffCalls.clear();
310
- this._shutdownSwitchoverBackoffCalls.clear();
311
- this._clearSeenAsyncEventIds();
312
- this._stopTokenRefreshTimer();
313
- this._connectPromises.clear();
194
+ this.stopTokenRefreshTimer();
314
195
  });
315
196
  }
316
- processRegistrationStatusEvent(message) {
317
- this.localClusterServiceUrls = message.localClusterServiceUrls;
318
- }
319
- _createWssResponseError(response, statusCode, statusMessage) {
197
+ createWssResponseError(response, statusCode, statusMessage) {
320
198
  const error = new Error(statusMessage || `Mobius websocket request failed with status ${statusCode || 'unknown'}`);
321
199
  error.name = 'MobiusSocketResponseError';
322
200
  error.statusCode = statusCode;
@@ -325,45 +203,36 @@ class MobiusSocket extends EventEmitter {
325
203
  error.trackingId = response?.trackingId;
326
204
  return error;
327
205
  }
328
- _applyOverrides(event) {
329
- if (!event || !event.headers) {
330
- return;
331
- }
332
- const headerKeys = Object.keys(event.headers);
333
- headerKeys.forEach((keyPath) => {
334
- set(event, keyPath, event.headers[keyPath]);
335
- });
336
- }
337
- _prepareUrl(webSocketUrl) {
206
+ prepareUrl(webSocketUrl) {
338
207
  if (!webSocketUrl) {
339
208
  webSocketUrl = this.webex.internal.device.webSocketUrl;
340
209
  }
341
210
  return Promise.resolve(webSocketUrl);
342
211
  }
343
- _attemptConnection(socketUrl, sessionId, callback, options = {}) {
212
+ attemptConnection(socketUrl, callback, options = {}) {
344
213
  const { isShutdownSwitchover = false, onSuccess = null } = options;
345
214
  const socket = new Socket();
346
215
  socket.connecting = true;
347
216
  let newWSUrl;
348
- this._attachSocketEventListeners(socket, sessionId);
217
+ this.attachSocketEventListeners(socket);
349
218
  const backoffCall = isShutdownSwitchover
350
- ? this._shutdownSwitchoverBackoffCalls.get(sessionId)
351
- : this.backoffCalls.get(sessionId);
219
+ ? this.shutdownSwitchoverBackoffCall
220
+ : this.backoffCall;
352
221
  if (!backoffCall) {
353
222
  const mode = isShutdownSwitchover ? 'switchover backoff call' : 'backoffCall';
354
- const msg = `${MOBIUS_SOCKET_NAMESPACE}: prevent socket open when ${mode} no longer defined for ${sessionId}`;
223
+ const msg = `${MOBIUS_SOCKET_NAMESPACE}: prevent socket open when ${mode} no longer defined`;
355
224
  const err = new Error(msg);
356
225
  this.logger.info(msg);
357
226
  callback(err);
358
227
  return Promise.reject(err);
359
228
  }
360
229
  if (!isShutdownSwitchover) {
361
- this.sockets.set(sessionId, socket);
230
+ this.socket = socket;
362
231
  }
363
- return this._prepareAndOpenSocket(socket, socketUrl, sessionId, isShutdownSwitchover)
232
+ return this.prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover)
364
233
  .then((webSocketUrl) => {
365
234
  newWSUrl = webSocketUrl;
366
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${isShutdownSwitchover ? '[shutdown] switchover' : ''} connected to mobius socket, success, action: connected for ${sessionId}, url: ${newWSUrl}`);
235
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${isShutdownSwitchover ? '[shutdown] switchover' : ''} connected to mobius socket, success, url: ${newWSUrl}`);
367
236
  if (onSuccess) {
368
237
  onSuccess(socket, webSocketUrl);
369
238
  callback();
@@ -374,48 +243,44 @@ class MobiusSocket extends EventEmitter {
374
243
  })
375
244
  .catch((reason) => {
376
245
  if (isShutdownSwitchover) {
377
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover attempt failed for ${sessionId}`, reason);
246
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] switchover attempt failed`, reason);
378
247
  return callback(reason);
379
248
  }
380
- this.lastError = reason;
381
- const backoffCallNormal = this.backoffCalls.get(sessionId);
249
+ const backoffCallNormal = this.backoffCall;
382
250
  if (reason.code !== 1006 && backoffCallNormal && backoffCallNormal?.getNumRetries() > 0) {
383
- this._emit(sessionId, 'connection_failed', reason, {
384
- sessionId,
251
+ this.emitEvent('connection_failed', reason, {
385
252
  retries: backoffCallNormal?.getNumRetries(),
386
253
  });
387
254
  }
388
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connection attempt failed for ${sessionId}`, reason, backoffCallNormal?.getNumRetries() === 0 ? reason.stack : '');
255
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connection attempt failed`, reason, backoffCallNormal?.getNumRetries() === 0 ? reason.stack : '');
389
256
  if (reason instanceof UnknownResponse) {
390
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: received unknown response code for ${sessionId}, refreshing device registration`);
257
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: received unknown response code, refreshing device registration`);
391
258
  return this.webex.internal.device.refresh().then(() => callback(reason));
392
259
  }
393
260
  if (reason instanceof NotAuthorized) {
394
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: received authorization error for ${sessionId}, reauthorizing`);
261
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: received authorization error, reauthorizing`);
395
262
  return this.webex.credentials.refresh({ force: true }).then(() => callback(reason));
396
263
  }
397
264
  if (reason instanceof BadRequest || reason instanceof Forbidden) {
398
- this.logger.warn(`${MOBIUS_SOCKET_NAMESPACE}: received unrecoverable response from ${MOBIUS_SOCKET_NAMESPACE} for ${sessionId}`);
265
+ this.logger.warn(`${MOBIUS_SOCKET_NAMESPACE}: received unrecoverable response from ${MOBIUS_SOCKET_NAMESPACE}`);
399
266
  backoffCallNormal?.abort();
400
267
  return callback(reason);
401
268
  }
402
269
  return callback(reason);
403
270
  })
404
271
  .catch((reason) => {
405
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: failed to handle connection failure for ${sessionId}`, reason);
272
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: failed to handle connection failure`, reason);
406
273
  callback(reason);
407
274
  });
408
275
  }
409
- _prepareAndOpenSocket(socket, socketUrl, sessionId, isShutdownSwitchover = false) {
276
+ prepareAndOpenSocket(socket, socketUrl, isShutdownSwitchover = false) {
410
277
  const logPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
411
- return Promise.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(([webSocketUrl, token]) => {
278
+ return Promise.all([this.prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(([webSocketUrl, token]) => {
412
279
  let options = {
413
280
  forceCloseDelay: this.config.forceCloseDelay,
414
281
  wssResponseTimeout: this.config.wssResponseTimeout,
415
- skipAckEventId: this.config.skipAckEventId,
416
- skipAckEventType: this.config.skipAckEventType,
417
282
  token: normalizeMobiusAuthToken(token.toString()),
418
- refreshToken: () => this._refreshToken(),
283
+ refreshToken: () => this.refreshToken(),
419
284
  trackingId: `${this.webex.sessionId}_${Date.now()}`,
420
285
  logger: this.logger,
421
286
  };
@@ -426,13 +291,14 @@ class MobiusSocket extends EventEmitter {
426
291
  this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${customOptionsMsg}`);
427
292
  options = { ...options, ...this.webex.config.defaultMobiusSocketOptions };
428
293
  }
429
- this.sockets.set(sessionId, socket);
430
- this.socket = this.sockets.get(this.defaultSessionId);
431
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE} ${logPrefix} url for ${sessionId}: ${webSocketUrl}`);
294
+ if (!isShutdownSwitchover) {
295
+ this.socket = socket;
296
+ }
297
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE} ${logPrefix} url: ${webSocketUrl}`);
432
298
  return socket.open(webSocketUrl, options).then(() => webSocketUrl);
433
299
  });
434
300
  }
435
- _connectWithBackoff(webSocketUrl, sessionId, context = {}) {
301
+ connectWithBackoff(webSocketUrl, context = {}) {
436
302
  const { isShutdownSwitchover = false, attemptOptions = {} } = context;
437
303
  return new Promise((resolve, reject) => {
438
304
  let call;
@@ -441,44 +307,43 @@ class MobiusSocket extends EventEmitter {
441
307
  ? null
442
308
  : Number(this.config.initialConnectionMaxRetries);
443
309
  const isInitialConnectWithoutRetries = isInitialConnect && initialRetryLimit === 0;
444
- const onComplete = (err, sid = sessionId) => {
310
+ const onComplete = (err) => {
445
311
  if (isShutdownSwitchover) {
446
- this._shutdownSwitchoverBackoffCalls.delete(sid);
312
+ this.shutdownSwitchoverBackoffCall = undefined;
447
313
  }
448
314
  else {
449
- this.backoffCalls.delete(sid);
315
+ this.backoffCall = undefined;
450
316
  }
451
- const sessionSocket = this.sockets.get(sid);
452
317
  if (err) {
453
318
  const msg = isShutdownSwitchover
454
319
  ? `[shutdown] switchover failed after ${call.getNumRetries()} retries`
455
320
  : `failed to connect after ${call.getNumRetries()} retries`;
456
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${msg}; log statement about next retry was inaccurate; ${err}`);
457
- if (sessionSocket) {
458
- sessionSocket.connecting = false;
459
- sessionSocket.connected = false;
321
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${msg}; ${err}`);
322
+ if (!isShutdownSwitchover && this.socket) {
323
+ this.socket.connecting = false;
324
+ this.socket.connected = false;
460
325
  }
461
326
  return reject(err);
462
327
  }
463
- if (sessionSocket) {
464
- sessionSocket.connecting = false;
465
- sessionSocket.connected = true;
328
+ if (!isShutdownSwitchover && this.socket) {
329
+ this.socket.connecting = false;
330
+ this.socket.connected = true;
466
331
  }
467
332
  if (!isShutdownSwitchover) {
468
- this.connecting = this.hasConnectingSockets();
469
- this.connected = this.hasConnectedSockets();
333
+ this.connecting = false;
334
+ this.connected = true;
470
335
  this.hasEverConnected = true;
471
- this._startTokenRefreshTimer();
472
- this._emit(sid, 'online');
336
+ this.startTokenRefreshTimer();
337
+ this.emitEvent('online');
473
338
  }
474
339
  return resolve();
475
340
  };
476
341
  call = backoff.call((callback) => {
477
342
  const attemptNum = call.getNumRetries();
478
343
  const attemptLogPrefix = isShutdownSwitchover ? '[shutdown] switchover' : 'connection';
479
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: executing ${attemptLogPrefix} attempt ${attemptNum} for ${sessionId}`);
480
- this._attemptConnection(webSocketUrl, sessionId, callback, attemptOptions);
481
- }, (err) => onComplete(err, sessionId));
344
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: executing ${attemptLogPrefix} attempt ${attemptNum}`);
345
+ this.attemptConnection(webSocketUrl, callback, attemptOptions);
346
+ }, (err) => onComplete(err));
482
347
  call.setStrategy(new backoff.ExponentialStrategy({
483
348
  initialDelay: this.config.backoffTimeReset,
484
349
  maxDelay: this.config.backoffTimeMax,
@@ -493,94 +358,70 @@ class MobiusSocket extends EventEmitter {
493
358
  call.failAfter(this.config.maxRetries);
494
359
  }
495
360
  if (isShutdownSwitchover) {
496
- this._shutdownSwitchoverBackoffCalls.set(sessionId, call);
361
+ this.shutdownSwitchoverBackoffCall = call;
497
362
  }
498
363
  else {
499
- this.backoffCalls.set(sessionId, call);
364
+ this.backoffCall = call;
500
365
  }
501
366
  call.on('abort', () => {
502
367
  const msg = isShutdownSwitchover ? 'Shutdown Switchover' : 'Connection';
503
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${msg} aborted for ${sessionId}`);
504
- reject(new Error(`MobiusSocket ${msg} Aborted for ${sessionId}`));
368
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${msg} aborted`);
369
+ reject(new Error(`MobiusSocket ${msg} Aborted`));
505
370
  });
506
371
  call.on('callback', (err) => {
507
372
  if (err) {
508
373
  if (isInitialConnectWithoutRetries) {
509
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: initial connect failed for ${sessionId}; retries already disabled`);
374
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: initial connect failed; retries already disabled`);
510
375
  return;
511
376
  }
512
377
  const number = call.getNumRetries();
513
378
  const delay = Math.min(call.strategy_.nextBackoffDelay_, this.config.backoffTimeMax);
514
379
  const callbackLogPrefix = isShutdownSwitchover ? '[shutdown] switchover' : '';
515
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${callbackLogPrefix} failed to connect; attempting retry ${number + 1} in ${delay} ms for ${sessionId}`);
380
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: ${callbackLogPrefix} failed to connect; attempting retry ${number + 1} in ${delay} ms`);
516
381
  if (process.env.NODE_ENV === 'development') {
517
382
  this.logger.debug(`${MOBIUS_SOCKET_NAMESPACE}: `, err, err.stack);
518
383
  }
519
384
  return;
520
385
  }
521
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connected ${sessionId}`);
386
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: connected`);
522
387
  });
523
388
  call.start();
524
389
  });
525
390
  }
526
- _emit(sessionId, eventName, ...args) {
391
+ emitEvent(eventName, ...args) {
527
392
  try {
528
- if (!sessionId || !eventName) {
393
+ if (!eventName) {
529
394
  return;
530
395
  }
531
- const suffix = sessionId === this.defaultSessionId ? '' : `:${sessionId}`;
532
- this.emit(`${eventName}${suffix}`, ...args);
396
+ this.emit(eventName, ...args);
533
397
  }
534
398
  catch (error) {
535
- try {
536
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred in event handler:`, error, ' with args: ', [sessionId, eventName, ...args]);
537
- }
538
- catch (logError) {
539
- console.error('MobiusSocket _emit error handling failed:', logError);
540
- }
399
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred in event handler:`, error, ' with args: ', [eventName, ...args]);
541
400
  }
542
401
  }
543
- _getEventHandlers(eventType) {
544
- if (!eventType) {
545
- return [];
546
- }
547
- const [namespace, name] = eventType.split('.');
548
- const handlers = [];
549
- if (!this.webex[namespace] && !this.webex.internal[namespace]) {
550
- return handlers;
551
- }
552
- const handlerName = camelCase(`process_${name}_event`);
553
- if ((this.webex[namespace] || this.webex.internal[namespace])[handlerName]) {
554
- handlers.push({
555
- name: handlerName,
556
- namespace,
557
- });
558
- }
559
- return handlers;
560
- }
561
- _startTokenRefreshTimer() {
562
- if (this._tokenRefreshTimer || !this.hasConnectedSockets()) {
402
+ startTokenRefreshTimer() {
403
+ if (this.tokenRefreshTimer || !this.connected) {
563
404
  return;
564
405
  }
565
- this._tokenRefreshTimer = setInterval(() => {
566
- this._refreshToken().catch((error) => {
406
+ this.tokenRefreshTimer = setInterval(() => {
407
+ this.refreshToken().catch((error) => {
567
408
  this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: periodic token refresh failed`, error);
568
409
  });
569
410
  }, TOKEN_REFRESH_INTERVAL_MS);
570
411
  }
571
- _stopTokenRefreshTimer() {
572
- if (!this._tokenRefreshTimer) {
412
+ stopTokenRefreshTimer() {
413
+ if (!this.tokenRefreshTimer) {
573
414
  return;
574
415
  }
575
- clearInterval(this._tokenRefreshTimer);
576
- this._tokenRefreshTimer = undefined;
416
+ clearInterval(this.tokenRefreshTimer);
417
+ this.tokenRefreshTimer = undefined;
577
418
  }
578
- _refreshToken() {
579
- if (this._tokenRefreshInFlight) {
580
- return this._tokenRefreshInFlight;
419
+ refreshToken() {
420
+ if (this.tokenRefreshInFlight) {
421
+ return this.tokenRefreshInFlight;
581
422
  }
582
- if (!this.hasConnectedSockets()) {
583
- this._stopTokenRefreshTimer();
423
+ if (!this.connected) {
424
+ this.stopTokenRefreshTimer();
584
425
  return Promise.resolve();
585
426
  }
586
427
  const tokenPromise = this.webex.credentials.canRefresh
@@ -588,176 +429,145 @@ class MobiusSocket extends EventEmitter {
588
429
  .refresh({ force: true })
589
430
  .then(() => this.webex.credentials.getUserToken())
590
431
  : this.webex.credentials.getUserToken();
591
- this._tokenRefreshInFlight = tokenPromise
432
+ this.tokenRefreshInFlight = tokenPromise
592
433
  .then((token) => {
593
434
  if (!token) {
594
435
  throw new Error('Mobius token refresh did not return a token');
595
436
  }
596
437
  const refreshedToken = normalizeMobiusAuthToken(token.toString());
597
- const authPayloadPromises = [];
598
- for (const socket of this.sockets.values()) {
599
- if (socket?.connected) {
600
- authPayloadPromises.push(socket.refresh(refreshedToken));
601
- }
438
+ if (this.socket?.connected) {
439
+ return this.socket.refresh(refreshedToken);
602
440
  }
603
- return Promise.all(authPayloadPromises);
441
+ return undefined;
604
442
  })
605
443
  .catch((error) => {
606
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: failed to refresh/re-auth Mobius sockets`, error);
444
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: failed to refresh/re-auth Mobius socket`, error);
607
445
  throw error;
608
446
  })
609
447
  .finally(() => {
610
- this._tokenRefreshInFlight = undefined;
448
+ this.tokenRefreshInFlight = undefined;
611
449
  });
612
- return this._tokenRefreshInFlight;
450
+ return this.tokenRefreshInFlight;
613
451
  }
614
- _onclose(sessionId, event, sourceSocket) {
452
+ onclose(event, sourceSocket) {
615
453
  try {
616
454
  const reason = event.reason && event.reason.toLowerCase();
617
- const sessionSocket = this.sockets.get(sessionId);
618
455
  let socketUrl;
619
- event.sessionId = sessionId;
620
- const isActiveSocket = sourceSocket === sessionSocket;
456
+ const isActiveSocket = sourceSocket === this.socket;
621
457
  if (sourceSocket) {
622
458
  socketUrl = sourceSocket.url;
623
459
  }
624
- this.sockets.delete(sessionId);
625
460
  if (isActiveSocket) {
626
- if (sessionSocket) {
627
- sessionSocket.removeAllListeners();
628
- if (sessionId === this.defaultSessionId) {
629
- this.socket = undefined;
630
- }
631
- this._emit(sessionId, 'offline', event);
632
- }
633
- this.connecting = this.hasConnectingSockets();
634
- this.connected = this.hasConnectedSockets();
635
- if (!this.hasConnectedSockets()) {
636
- this._stopTokenRefreshTimer();
461
+ if (this.socket) {
462
+ this.socket.removeAllListeners();
463
+ this.socket = undefined;
464
+ this.emitEvent('offline', event);
637
465
  }
466
+ this.connecting = false;
467
+ this.connected = false;
468
+ this.stopTokenRefreshTimer();
638
469
  }
639
470
  else {
640
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] non-active socket closed, code=${event.code} for ${sessionId}`);
471
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] non-active socket closed, code=${event.code}`);
641
472
  if (sourceSocket) {
642
473
  sourceSocket.removeAllListeners();
643
474
  }
644
475
  }
645
476
  switch (event.code) {
646
477
  case 1003:
647
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: service rejected last message for ${sessionId}; will not reconnect: ${event.reason}`);
478
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: service rejected last message; will not reconnect: ${event.reason}`);
648
479
  if (isActiveSocket)
649
- this._emit(sessionId, 'offline.permanent', event);
480
+ this.emitEvent('offline.permanent', event);
650
481
  break;
651
482
  case 4000:
652
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket ${sessionId} replaced; will not reconnect`);
483
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket replaced; will not reconnect`);
653
484
  if (isActiveSocket)
654
- this._emit(sessionId, 'offline.replaced', event);
485
+ this.emitEvent('offline.replaced', event);
655
486
  break;
656
487
  case 4001:
657
488
  if (isActiveSocket) {
658
- this.logger.warn(`${MOBIUS_SOCKET_NAMESPACE}: active socket closed with 4001; shutdown switchover failed for ${sessionId}`);
659
- this._emit(sessionId, 'offline.permanent', event);
489
+ this.logger.warn(`${MOBIUS_SOCKET_NAMESPACE}: active socket closed with 4001; shutdown switchover failed`);
490
+ this.emitEvent('offline.permanent', event);
660
491
  }
661
492
  else {
662
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: old socket closed with 4001 (replaced during shutdown); no reconnect needed for ${sessionId}`);
663
- this._emit(sessionId, 'offline.replaced', event);
493
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: old socket closed with 4001 (replaced during shutdown); no reconnect needed`);
494
+ this.emitEvent('offline.replaced', event);
664
495
  }
665
496
  break;
666
497
  case 1001:
667
498
  case 1005:
668
499
  case 1006:
669
500
  case 1011:
670
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket ${sessionId} disconnected; reconnecting`);
501
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket disconnected; reconnecting`);
671
502
  if (isActiveSocket) {
672
- this._emit(sessionId, 'offline.transient', event);
673
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] reconnecting active socket to recover for ${sessionId}`);
674
- this._reconnect(socketUrl, sessionId);
503
+ this.emitEvent('offline.transient', event);
504
+ this.reconnect(socketUrl);
675
505
  }
676
506
  break;
677
507
  case 1000:
678
508
  case 3050:
679
509
  if (normalReconnectReasons.includes(reason)) {
680
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket ${sessionId} disconnected; reconnecting`);
510
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket disconnected; reconnecting`);
681
511
  if (isActiveSocket) {
682
- this._emit(sessionId, 'offline.transient', event);
683
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] reconnecting due to normal close for ${sessionId}`);
684
- this._reconnect(socketUrl, sessionId);
512
+ this.emitEvent('offline.transient', event);
513
+ this.reconnect(socketUrl);
685
514
  }
686
515
  }
687
516
  else {
688
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket ${sessionId} disconnected; will not reconnect: ${event.reason}`);
517
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket disconnected; will not reconnect: ${event.reason}`);
689
518
  if (isActiveSocket)
690
- this._emit(sessionId, 'offline.permanent', event);
519
+ this.emitEvent('offline.permanent', event);
691
520
  }
692
521
  break;
693
522
  default:
694
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket ${sessionId} disconnected unexpectedly; will not reconnect`);
523
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: socket disconnected unexpectedly; will not reconnect`);
695
524
  if (isActiveSocket)
696
- this._emit(sessionId, 'offline.permanent', event);
525
+ this.emitEvent('offline.permanent', event);
697
526
  }
698
527
  }
699
528
  catch (error) {
700
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred in close handler for ${sessionId}`, error);
529
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred in close handler`, error);
701
530
  }
702
531
  }
703
- _onmessage(sessionId, event) {
704
- this._setTimeOffset(sessionId, event);
532
+ onmessage(event) {
705
533
  const envelope = event.data;
706
- if (process.env.ENABLE_MERCURY_LOGGING) {
707
- this.logger.debug(`${MOBIUS_SOCKET_NAMESPACE}: message envelope from ${sessionId}: `, envelope);
534
+ if (process.env.ENABLE_MOBIUS_LOGGING) {
535
+ this.logger.debug(`${MOBIUS_SOCKET_NAMESPACE}: message envelope: `, envelope);
708
536
  }
709
- envelope.sessionId = sessionId;
710
537
  if (envelope && envelope.type === 'shutdown') {
711
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] imminent shutdown message received for ${sessionId}`);
712
- this._emit(sessionId, 'event:mercury_shutdown_imminent', envelope);
713
- this._handleImminentShutdown(sessionId);
538
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: [shutdown] imminent shutdown message received`);
539
+ this.emitEvent('event:mobius_shutdown_imminent', envelope);
540
+ this.handleImminentShutdown();
714
541
  return Promise.resolve();
715
542
  }
716
- if (this._trackAsyncEventAndShouldSuppressDuplicate(sessionId, envelope)) {
543
+ if (this.trackAsyncEventAndShouldSuppressDuplicate(envelope)) {
717
544
  return Promise.resolve();
718
545
  }
719
546
  if (envelope.type) {
720
- this._emit(sessionId, `event:${envelope.type}`, envelope);
547
+ this.emitEvent(`event:${envelope.type}`, envelope);
721
548
  }
722
- envelope.sessionId = sessionId;
723
549
  const data = envelope.data || envelope;
724
- this._applyOverrides(data);
725
550
  const eventType = data?.eventType || envelope.eventType;
726
551
  if (!eventType) {
727
- this._emit(sessionId, 'event', envelope);
552
+ this.emitEvent('event', envelope);
728
553
  return Promise.resolve();
729
554
  }
730
- return this._getEventHandlers(eventType)
731
- .reduce((promise, handler) => promise.then(() => {
732
- const { namespace, name } = handler;
733
- return new Promise((resolve) => {
734
- resolve((this.webex[namespace] || this.webex.internal[namespace])[name](data));
735
- }).catch((reason) => this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred in autowired event handler for ${eventType} from ${sessionId}`, reason));
736
- }), Promise.resolve())
737
- .then(() => {
738
- this._emit(sessionId, 'event', envelope);
555
+ try {
556
+ this.emitEvent('event', envelope);
739
557
  const [namespace] = eventType.split('.');
740
- if (namespace === eventType) {
741
- this._emit(sessionId, `event:${namespace}`, envelope);
558
+ this.emitEvent(`event:${namespace}`, envelope);
559
+ if (namespace !== eventType) {
560
+ this.emitEvent(`event:${eventType}`, envelope);
742
561
  }
743
- else {
744
- this._emit(sessionId, `event:${namespace}`, envelope);
745
- this._emit(sessionId, `event:${eventType}`, envelope);
746
- }
747
- })
748
- .catch((reason) => {
749
- this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred processing socket message from ${sessionId}`, reason);
750
- });
751
- }
752
- _setTimeOffset(sessionId, event) {
753
- const { wsWriteTimestamp } = event.data;
754
- if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
755
- this.mercuryTimeOffset = Date.now() - wsWriteTimestamp;
756
562
  }
563
+ catch (reason) {
564
+ this.logger.error(`${MOBIUS_SOCKET_NAMESPACE}: error occurred processing socket message`, reason);
565
+ }
566
+ return Promise.resolve();
757
567
  }
758
- _reconnect(webSocketUrl, sessionId = this.defaultSessionId) {
759
- this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: reconnecting ${sessionId}`);
760
- return this.connect(webSocketUrl || this.socketUrl, sessionId);
568
+ reconnect(webSocketUrl) {
569
+ this.logger.info(`${MOBIUS_SOCKET_NAMESPACE}: reconnecting`);
570
+ return this.connect(webSocketUrl || this.socketUrl);
761
571
  }
762
572
  }
763
573
  export default MobiusSocket;