@webex/internal-plugin-mercury 3.11.0-next.7 → 3.11.0-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/mercury.js +386 -198
- package/dist/mercury.js.map +1 -1
- package/dist/socket/constants.js +16 -0
- package/dist/socket/constants.js.map +1 -0
- package/dist/socket/socket-base.js +17 -3
- package/dist/socket/socket-base.js.map +1 -1
- package/package.json +5 -5
- package/src/mercury.js +383 -171
- package/src/socket/constants.js +6 -0
- package/src/socket/socket-base.js +20 -3
- package/test/unit/spec/mercury-events.js +20 -2
- package/test/unit/spec/mercury.js +201 -139
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
UnknownResponse,
|
|
18
18
|
// NotFound
|
|
19
19
|
} from '../errors';
|
|
20
|
+
import {SOCKET_READY_STATE} from './constants';
|
|
20
21
|
|
|
21
22
|
const sockets = new WeakMap();
|
|
22
23
|
|
|
@@ -33,6 +34,8 @@ export default class Socket extends EventEmitter {
|
|
|
33
34
|
this._domain = 'unknown-domain';
|
|
34
35
|
this.onmessage = this.onmessage.bind(this);
|
|
35
36
|
this.onclose = this.onclose.bind(this);
|
|
37
|
+
// Increase max listeners to avoid memory leak warning in tests
|
|
38
|
+
this.setMaxListeners(10);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
@@ -114,7 +117,10 @@ export default class Socket extends EventEmitter {
|
|
|
114
117
|
// logger is defined once open is called
|
|
115
118
|
this.logger.info(`socket,${this._domain}: closing`);
|
|
116
119
|
|
|
117
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
socket.readyState === SOCKET_READY_STATE.CLOSING ||
|
|
122
|
+
socket.readyState === SOCKET_READY_STATE.CLOSED
|
|
123
|
+
) {
|
|
118
124
|
this.logger.info(`socket,${this._domain}: already closed`);
|
|
119
125
|
resolve();
|
|
120
126
|
|
|
@@ -163,7 +169,7 @@ export default class Socket extends EventEmitter {
|
|
|
163
169
|
|
|
164
170
|
// If socket is still connecting, manually trigger close handler with desired code
|
|
165
171
|
// because calling close() on a CONNECTING socket may not preserve custom codes
|
|
166
|
-
if (socket.readyState ===
|
|
172
|
+
if (socket.readyState === SOCKET_READY_STATE.CONNECTING) {
|
|
167
173
|
this.logger.info(
|
|
168
174
|
`socket,${this._domain}: socket still connecting, triggering close manually`
|
|
169
175
|
);
|
|
@@ -348,7 +354,7 @@ export default class Socket extends EventEmitter {
|
|
|
348
354
|
*/
|
|
349
355
|
send(data) {
|
|
350
356
|
return new Promise((resolve, reject) => {
|
|
351
|
-
if (this.readyState !==
|
|
357
|
+
if (this.readyState !== SOCKET_READY_STATE.OPEN) {
|
|
352
358
|
return reject(new Error('INVALID_STATE_ERROR'));
|
|
353
359
|
}
|
|
354
360
|
|
|
@@ -378,9 +384,20 @@ export default class Socket extends EventEmitter {
|
|
|
378
384
|
return Promise.reject(new Error('`event.data.id` is required'));
|
|
379
385
|
}
|
|
380
386
|
|
|
387
|
+
// Don't try to acknowledge if socket is not in open state
|
|
388
|
+
if (this.readyState !== SOCKET_READY_STATE.OPEN) {
|
|
389
|
+
return Promise.resolve(); // Silently ignore acknowledgment for closed sockets
|
|
390
|
+
}
|
|
391
|
+
|
|
381
392
|
return this.send({
|
|
382
393
|
messageId: event.data.id,
|
|
383
394
|
type: 'ack',
|
|
395
|
+
}).catch((error) => {
|
|
396
|
+
// Gracefully handle send errors (like INVALID_STATE_ERROR) to prevent test issues
|
|
397
|
+
if (error.message === 'INVALID_STATE_ERROR') {
|
|
398
|
+
return Promise.resolve(); // Socket was closed, ignore the acknowledgment
|
|
399
|
+
}
|
|
400
|
+
throw error; // Re-throw other errors
|
|
384
401
|
});
|
|
385
402
|
}
|
|
386
403
|
|
|
@@ -38,14 +38,31 @@ describe('plugin-mercury', () => {
|
|
|
38
38
|
},
|
|
39
39
|
timestamp: Date.now(),
|
|
40
40
|
trackingId: `suffix_${uuid.v4()}_${Date.now()}`,
|
|
41
|
+
sessionId: 'mercury-default-session',
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
beforeEach(() => {
|
|
44
45
|
clock = FakeTimers.install({now: Date.now()});
|
|
45
46
|
});
|
|
46
47
|
|
|
47
|
-
afterEach(() => {
|
|
48
|
+
afterEach(async () => {
|
|
48
49
|
clock.uninstall();
|
|
50
|
+
// Clean up mercury socket and mockWebSocket
|
|
51
|
+
if (mercury && mercury.socket) {
|
|
52
|
+
try {
|
|
53
|
+
await mercury.socket.close();
|
|
54
|
+
} catch (e) {}
|
|
55
|
+
}
|
|
56
|
+
if (mockWebSocket && typeof mockWebSocket.close === 'function') {
|
|
57
|
+
mockWebSocket.close();
|
|
58
|
+
}
|
|
59
|
+
// Restore stubs
|
|
60
|
+
if (Socket.getWebSocketConstructor.restore) {
|
|
61
|
+
Socket.getWebSocketConstructor.restore();
|
|
62
|
+
}
|
|
63
|
+
if (socketOpenStub && socketOpenStub.restore) {
|
|
64
|
+
socketOpenStub.restore();
|
|
65
|
+
}
|
|
49
66
|
});
|
|
50
67
|
|
|
51
68
|
beforeEach(() => {
|
|
@@ -76,6 +93,7 @@ describe('plugin-mercury', () => {
|
|
|
76
93
|
});
|
|
77
94
|
|
|
78
95
|
mercury = webex.internal.mercury;
|
|
96
|
+
mercury.defaultSessionId = 'mercury-default-session';
|
|
79
97
|
});
|
|
80
98
|
|
|
81
99
|
afterEach(() => {
|
|
@@ -301,7 +319,7 @@ describe('plugin-mercury', () => {
|
|
|
301
319
|
})
|
|
302
320
|
.then(() => {
|
|
303
321
|
assert.called(offlineSpy);
|
|
304
|
-
assert.calledWith(offlineSpy, {code, reason});
|
|
322
|
+
assert.calledWith(offlineSpy, {code, reason, sessionId: 'mercury-default-session'});
|
|
305
323
|
switch (action) {
|
|
306
324
|
case 'close':
|
|
307
325
|
assert.called(permanentSpy);
|