genesys-cloud-streaming-client 17.1.2-develop.96 → 17.1.2-develop.97
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/cjs/client.d.ts +2 -0
- package/dist/cjs/client.js +31 -5
- package/dist/cjs/server-monitor.d.ts +16 -0
- package/dist/cjs/server-monitor.js +42 -0
- package/dist/cjs/types/interfaces.d.ts +1 -0
- package/dist/cjs/types/named-agent.d.ts +2 -0
- package/dist/deploy-info.json +2 -2
- package/dist/es/client.d.ts +2 -0
- package/dist/es/client.js +33 -5
- package/dist/es/index.bundle.js +71 -5
- package/dist/es/server-monitor.d.ts +16 -0
- package/dist/es/server-monitor.js +39 -0
- package/dist/es/types/interfaces.d.ts +1 -0
- package/dist/es/types/named-agent.d.ts +2 -0
- package/dist/npm/CHANGELOG.md +2 -0
- package/dist/npm/client.d.ts +2 -0
- package/dist/npm/client.js +31 -5
- package/dist/npm/server-monitor.d.ts +16 -0
- package/dist/npm/server-monitor.js +42 -0
- package/dist/npm/types/interfaces.d.ts +1 -0
- package/dist/npm/types/named-agent.d.ts +2 -0
- package/dist/streaming-client.browser.ie.js +6 -6
- package/dist/streaming-client.browser.js +5 -5
- package/dist/v17/streaming-client.browser.ie.js +6 -6
- package/dist/v17/streaming-client.browser.js +5 -5
- package/dist/v17.1.2/streaming-client.browser.ie.js +6 -6
- package/dist/v17.1.2/streaming-client.browser.js +5 -5
- package/package.json +1 -1
package/dist/cjs/client.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class Client extends EventEmitter {
|
|
|
16
16
|
connecting: boolean;
|
|
17
17
|
hardReconnectRequired: boolean;
|
|
18
18
|
reconnectOnNoLongerSubscribed: boolean;
|
|
19
|
+
useServerSidePings: boolean;
|
|
19
20
|
logger: Logger;
|
|
20
21
|
config: IClientConfig;
|
|
21
22
|
isGuest: boolean;
|
|
@@ -55,6 +56,7 @@ export declare class Client extends EventEmitter {
|
|
|
55
56
|
connect(connectOpts?: StreamingClientConnectOptions): Promise<void>;
|
|
56
57
|
private backoffConnectRetryHandler;
|
|
57
58
|
private makeConnectionAttempt;
|
|
59
|
+
private setupConnectionMonitoring;
|
|
58
60
|
private prepareForConnect;
|
|
59
61
|
stopServerLogging(): void;
|
|
60
62
|
startServerLogging(): void;
|
package/dist/cjs/client.js
CHANGED
|
@@ -8,6 +8,7 @@ require("./polyfills");
|
|
|
8
8
|
const notifications_1 = require("./notifications");
|
|
9
9
|
const webrtc_1 = require("./webrtc");
|
|
10
10
|
const ping_1 = require("./ping");
|
|
11
|
+
const server_monitor_1 = require("./server-monitor");
|
|
11
12
|
const utils_1 = require("./utils");
|
|
12
13
|
const http_client_1 = require("./http-client");
|
|
13
14
|
const events_1 = tslib_1.__importDefault(require("events"));
|
|
@@ -43,6 +44,7 @@ class Client extends events_1.default {
|
|
|
43
44
|
this.hasMadeInitialAttempt = false;
|
|
44
45
|
this.http = new http_client_1.HttpClient();
|
|
45
46
|
this.reconnectOnNoLongerSubscribed = options.reconnectOnNoLongerSubscribed !== false;
|
|
47
|
+
this.useServerSidePings = options.useServerSidePings !== false;
|
|
46
48
|
this.config = {
|
|
47
49
|
host: options.host,
|
|
48
50
|
apiHost: options.apiHost || options.host.replace('wss://streaming.', ''),
|
|
@@ -175,11 +177,12 @@ class Client extends events_1.default {
|
|
|
175
177
|
};
|
|
176
178
|
}
|
|
177
179
|
async handleStanzaDisconnectedEvent(disconnectedInstance) {
|
|
178
|
-
var _a;
|
|
180
|
+
var _a, _b;
|
|
179
181
|
this.logger.info('stanzaDisconnected event received', { stanzaInstanceId: disconnectedInstance.id, channelId: disconnectedInstance.channelId });
|
|
180
182
|
this.connected = false;
|
|
181
183
|
this.connecting = false;
|
|
182
184
|
(_a = disconnectedInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
185
|
+
(_b = disconnectedInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
183
186
|
this.removeAllListeners(STANZA_DISCONNECTED);
|
|
184
187
|
this.removeAllListeners(NO_LONGER_SUBSCRIBED);
|
|
185
188
|
// unproxy events
|
|
@@ -193,18 +196,20 @@ class Client extends events_1.default {
|
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
198
|
handleNoLongerSubscribed(stanzaInstance) {
|
|
196
|
-
var _a;
|
|
199
|
+
var _a, _b;
|
|
197
200
|
this.logger.warn('noLongerSubscribed event received', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
198
201
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
202
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
199
203
|
this.hardReconnectRequired = true;
|
|
200
204
|
if (!this.reconnectOnNoLongerSubscribed) {
|
|
201
205
|
this.autoReconnect = false;
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
handleDuplicateId(stanzaInstance) {
|
|
205
|
-
var _a;
|
|
209
|
+
var _a, _b;
|
|
206
210
|
this.logger.warn('duplicate_id event received, forcing hard reconnect', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
207
211
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
212
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
208
213
|
this.hardReconnectRequired = true;
|
|
209
214
|
}
|
|
210
215
|
async disconnect() {
|
|
@@ -407,7 +412,7 @@ class Client extends events_1.default {
|
|
|
407
412
|
return true;
|
|
408
413
|
}
|
|
409
414
|
async makeConnectionAttempt() {
|
|
410
|
-
var _a;
|
|
415
|
+
var _a, _b;
|
|
411
416
|
if (!navigator.onLine) {
|
|
412
417
|
throw new offline_error_1.default('Browser is offline, skipping connection attempt');
|
|
413
418
|
}
|
|
@@ -430,7 +435,7 @@ class Client extends events_1.default {
|
|
|
430
435
|
extension.handleStanzaInstanceChange(stanzaInstance);
|
|
431
436
|
}
|
|
432
437
|
this.activeStanzaInstance = stanzaInstance;
|
|
433
|
-
|
|
438
|
+
await this.setupConnectionMonitoring(stanzaInstance);
|
|
434
439
|
this.emit('connected');
|
|
435
440
|
}
|
|
436
441
|
catch (err) {
|
|
@@ -438,6 +443,7 @@ class Client extends events_1.default {
|
|
|
438
443
|
this.logger.error('Error occurred in connection attempt, but after websocket connected. Cleaning up connection so backoff is respected', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
439
444
|
this.removeStanzaBoundEventHandlers();
|
|
440
445
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
446
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
441
447
|
await stanzaInstance.disconnect();
|
|
442
448
|
this.connected = false;
|
|
443
449
|
this.connecting = previousConnectingState;
|
|
@@ -445,6 +451,26 @@ class Client extends events_1.default {
|
|
|
445
451
|
throw err;
|
|
446
452
|
}
|
|
447
453
|
}
|
|
454
|
+
async setupConnectionMonitoring(stanzaInstance) {
|
|
455
|
+
const setupClientPinger = (message) => {
|
|
456
|
+
const logMessage = `$(message), falling back to client-side pinging`;
|
|
457
|
+
this.logger.warn(logMessage, { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
458
|
+
stanzaInstance.pinger = new ping_1.Ping(this, stanzaInstance);
|
|
459
|
+
};
|
|
460
|
+
if (this.useServerSidePings) {
|
|
461
|
+
try {
|
|
462
|
+
// if this fails, then hawk doesn't support serverside pinging and we need to do client side pings
|
|
463
|
+
await stanzaInstance.subscribeToNode(this._notifications.pubsubHost, 'enable.server.side.pings');
|
|
464
|
+
stanzaInstance.serverMonitor = new server_monitor_1.ServerMonitor(this, stanzaInstance);
|
|
465
|
+
}
|
|
466
|
+
catch (err) {
|
|
467
|
+
setupClientPinger('failed to establish server-side pinging');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
setupClientPinger('client configured to not use server-side pinging');
|
|
472
|
+
}
|
|
473
|
+
}
|
|
448
474
|
async prepareForConnect() {
|
|
449
475
|
if (this.config.jwt) {
|
|
450
476
|
this.hardReconnectRequired = false;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Client } from './client';
|
|
2
|
+
import { NamedAgent } from './types/named-agent';
|
|
3
|
+
export interface ServerMonitorOptions {
|
|
4
|
+
stanzaTimeout?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class ServerMonitor {
|
|
7
|
+
private client;
|
|
8
|
+
private stanzaInstance;
|
|
9
|
+
private stanzaTimeout;
|
|
10
|
+
private timeoutId?;
|
|
11
|
+
private boundSetupStanzaTimeout?;
|
|
12
|
+
constructor(client: Client, stanzaInstance: NamedAgent, options?: ServerMonitorOptions);
|
|
13
|
+
private start;
|
|
14
|
+
stop(): void;
|
|
15
|
+
private setupStanzaTimeout;
|
|
16
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServerMonitor = void 0;
|
|
4
|
+
const DEFAULT_STANZA_TIMEOUT = 70 * 1000;
|
|
5
|
+
class ServerMonitor {
|
|
6
|
+
constructor(client, stanzaInstance, options = {}) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
this.stanzaInstance = stanzaInstance;
|
|
9
|
+
this.stanzaTimeout = options.stanzaTimeout || DEFAULT_STANZA_TIMEOUT;
|
|
10
|
+
this.timeoutId = undefined;
|
|
11
|
+
this.start();
|
|
12
|
+
}
|
|
13
|
+
start() {
|
|
14
|
+
this.boundSetupStanzaTimeout = this.setupStanzaTimeout.bind(this);
|
|
15
|
+
this.client.on('connected', this.boundSetupStanzaTimeout);
|
|
16
|
+
this.stanzaInstance.on('raw:incoming', this.boundSetupStanzaTimeout);
|
|
17
|
+
}
|
|
18
|
+
stop() {
|
|
19
|
+
clearTimeout(this.timeoutId);
|
|
20
|
+
this.timeoutId = undefined;
|
|
21
|
+
if (this.boundSetupStanzaTimeout) {
|
|
22
|
+
this.client.off('connected', this.boundSetupStanzaTimeout);
|
|
23
|
+
this.stanzaInstance.off('raw:incoming', this.boundSetupStanzaTimeout);
|
|
24
|
+
this.boundSetupStanzaTimeout = undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
setupStanzaTimeout() {
|
|
28
|
+
clearTimeout(this.timeoutId);
|
|
29
|
+
this.timeoutId = setTimeout(() => {
|
|
30
|
+
const info = {
|
|
31
|
+
channelId: this.client.config.channelId,
|
|
32
|
+
jid: this.stanzaInstance.jid,
|
|
33
|
+
stanzaInstanceId: this.stanzaInstance.id,
|
|
34
|
+
timeout: this.stanzaTimeout
|
|
35
|
+
};
|
|
36
|
+
this.client.logger.error('Time between XMPP stanzas exceeded timeout, disconnecting', info);
|
|
37
|
+
this.stanzaInstance.sendStreamError({ text: 'time between stanzas exceeded timeout', condition: 'connection-timeout' });
|
|
38
|
+
this.stop();
|
|
39
|
+
}, this.stanzaTimeout);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.ServerMonitor = ServerMonitor;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Agent } from 'stanza';
|
|
2
2
|
import { Ping } from '../ping';
|
|
3
|
+
import { ServerMonitor } from '../server-monitor';
|
|
3
4
|
export interface NamedAgent extends Omit<Agent, 'disconnect'> {
|
|
4
5
|
id: string;
|
|
5
6
|
channelId?: string;
|
|
6
7
|
originalEmitter?: Function;
|
|
7
8
|
pinger?: Ping;
|
|
9
|
+
serverMonitor?: ServerMonitor;
|
|
8
10
|
disconnect: () => Promise<void>;
|
|
9
11
|
}
|
package/dist/deploy-info.json
CHANGED
package/dist/es/client.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class Client extends EventEmitter {
|
|
|
16
16
|
connecting: boolean;
|
|
17
17
|
hardReconnectRequired: boolean;
|
|
18
18
|
reconnectOnNoLongerSubscribed: boolean;
|
|
19
|
+
useServerSidePings: boolean;
|
|
19
20
|
logger: Logger;
|
|
20
21
|
config: IClientConfig;
|
|
21
22
|
isGuest: boolean;
|
|
@@ -55,6 +56,7 @@ export declare class Client extends EventEmitter {
|
|
|
55
56
|
connect(connectOpts?: StreamingClientConnectOptions): Promise<void>;
|
|
56
57
|
private backoffConnectRetryHandler;
|
|
57
58
|
private makeConnectionAttempt;
|
|
59
|
+
private setupConnectionMonitoring;
|
|
58
60
|
private prepareForConnect;
|
|
59
61
|
stopServerLogging(): void;
|
|
60
62
|
startServerLogging(): void;
|
package/dist/es/client.js
CHANGED
|
@@ -6,6 +6,7 @@ import './polyfills';
|
|
|
6
6
|
import { Notifications } from './notifications';
|
|
7
7
|
import { WebrtcExtension } from './webrtc';
|
|
8
8
|
import { Ping } from './ping';
|
|
9
|
+
import { ServerMonitor } from './server-monitor';
|
|
9
10
|
import { delay, parseJwt, timeoutPromise } from './utils';
|
|
10
11
|
import { HttpClient } from './http-client';
|
|
11
12
|
import EventEmitter from 'events';
|
|
@@ -41,6 +42,7 @@ export class Client extends EventEmitter {
|
|
|
41
42
|
this.hasMadeInitialAttempt = false;
|
|
42
43
|
this.http = new HttpClient();
|
|
43
44
|
this.reconnectOnNoLongerSubscribed = options.reconnectOnNoLongerSubscribed !== false;
|
|
45
|
+
this.useServerSidePings = options.useServerSidePings !== false;
|
|
44
46
|
this.config = {
|
|
45
47
|
host: options.host,
|
|
46
48
|
apiHost: options.apiHost || options.host.replace('wss://streaming.', ''),
|
|
@@ -173,12 +175,13 @@ export class Client extends EventEmitter {
|
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
handleStanzaDisconnectedEvent(disconnectedInstance) {
|
|
176
|
-
var _a;
|
|
178
|
+
var _a, _b;
|
|
177
179
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
180
|
this.logger.info('stanzaDisconnected event received', { stanzaInstanceId: disconnectedInstance.id, channelId: disconnectedInstance.channelId });
|
|
179
181
|
this.connected = false;
|
|
180
182
|
this.connecting = false;
|
|
181
183
|
(_a = disconnectedInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
184
|
+
(_b = disconnectedInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
182
185
|
this.removeAllListeners(STANZA_DISCONNECTED);
|
|
183
186
|
this.removeAllListeners(NO_LONGER_SUBSCRIBED);
|
|
184
187
|
// unproxy events
|
|
@@ -193,18 +196,20 @@ export class Client extends EventEmitter {
|
|
|
193
196
|
});
|
|
194
197
|
}
|
|
195
198
|
handleNoLongerSubscribed(stanzaInstance) {
|
|
196
|
-
var _a;
|
|
199
|
+
var _a, _b;
|
|
197
200
|
this.logger.warn('noLongerSubscribed event received', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
198
201
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
202
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
199
203
|
this.hardReconnectRequired = true;
|
|
200
204
|
if (!this.reconnectOnNoLongerSubscribed) {
|
|
201
205
|
this.autoReconnect = false;
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
handleDuplicateId(stanzaInstance) {
|
|
205
|
-
var _a;
|
|
209
|
+
var _a, _b;
|
|
206
210
|
this.logger.warn('duplicate_id event received, forcing hard reconnect', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
207
211
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
212
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
208
213
|
this.hardReconnectRequired = true;
|
|
209
214
|
}
|
|
210
215
|
disconnect() {
|
|
@@ -413,7 +418,7 @@ export class Client extends EventEmitter {
|
|
|
413
418
|
});
|
|
414
419
|
}
|
|
415
420
|
makeConnectionAttempt() {
|
|
416
|
-
var _a;
|
|
421
|
+
var _a, _b;
|
|
417
422
|
return __awaiter(this, void 0, void 0, function* () {
|
|
418
423
|
if (!navigator.onLine) {
|
|
419
424
|
throw new OfflineError('Browser is offline, skipping connection attempt');
|
|
@@ -437,7 +442,7 @@ export class Client extends EventEmitter {
|
|
|
437
442
|
extension.handleStanzaInstanceChange(stanzaInstance);
|
|
438
443
|
}
|
|
439
444
|
this.activeStanzaInstance = stanzaInstance;
|
|
440
|
-
|
|
445
|
+
yield this.setupConnectionMonitoring(stanzaInstance);
|
|
441
446
|
this.emit('connected');
|
|
442
447
|
}
|
|
443
448
|
catch (err) {
|
|
@@ -445,6 +450,7 @@ export class Client extends EventEmitter {
|
|
|
445
450
|
this.logger.error('Error occurred in connection attempt, but after websocket connected. Cleaning up connection so backoff is respected', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
446
451
|
this.removeStanzaBoundEventHandlers();
|
|
447
452
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
453
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
448
454
|
yield stanzaInstance.disconnect();
|
|
449
455
|
this.connected = false;
|
|
450
456
|
this.connecting = previousConnectingState;
|
|
@@ -453,6 +459,28 @@ export class Client extends EventEmitter {
|
|
|
453
459
|
}
|
|
454
460
|
});
|
|
455
461
|
}
|
|
462
|
+
setupConnectionMonitoring(stanzaInstance) {
|
|
463
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
464
|
+
const setupClientPinger = (message) => {
|
|
465
|
+
const logMessage = `$(message), falling back to client-side pinging`;
|
|
466
|
+
this.logger.warn(logMessage, { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
467
|
+
stanzaInstance.pinger = new Ping(this, stanzaInstance);
|
|
468
|
+
};
|
|
469
|
+
if (this.useServerSidePings) {
|
|
470
|
+
try {
|
|
471
|
+
// if this fails, then hawk doesn't support serverside pinging and we need to do client side pings
|
|
472
|
+
yield stanzaInstance.subscribeToNode(this._notifications.pubsubHost, 'enable.server.side.pings');
|
|
473
|
+
stanzaInstance.serverMonitor = new ServerMonitor(this, stanzaInstance);
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
setupClientPinger('failed to establish server-side pinging');
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
setupClientPinger('client configured to not use server-side pinging');
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}
|
|
456
484
|
prepareForConnect() {
|
|
457
485
|
return __awaiter(this, void 0, void 0, function* () {
|
|
458
486
|
if (this.config.jwt) {
|
package/dist/es/index.bundle.js
CHANGED
|
@@ -31444,6 +31444,45 @@ class Ping {
|
|
|
31444
31444
|
}
|
|
31445
31445
|
}
|
|
31446
31446
|
|
|
31447
|
+
const DEFAULT_STANZA_TIMEOUT = 70 * 1000;
|
|
31448
|
+
class ServerMonitor {
|
|
31449
|
+
constructor(client, stanzaInstance, options = {}) {
|
|
31450
|
+
this.client = client;
|
|
31451
|
+
this.stanzaInstance = stanzaInstance;
|
|
31452
|
+
this.stanzaTimeout = options.stanzaTimeout || DEFAULT_STANZA_TIMEOUT;
|
|
31453
|
+
this.timeoutId = undefined;
|
|
31454
|
+
this.start();
|
|
31455
|
+
}
|
|
31456
|
+
start() {
|
|
31457
|
+
this.boundSetupStanzaTimeout = this.setupStanzaTimeout.bind(this);
|
|
31458
|
+
this.client.on('connected', this.boundSetupStanzaTimeout);
|
|
31459
|
+
this.stanzaInstance.on('raw:incoming', this.boundSetupStanzaTimeout);
|
|
31460
|
+
}
|
|
31461
|
+
stop() {
|
|
31462
|
+
clearTimeout(this.timeoutId);
|
|
31463
|
+
this.timeoutId = undefined;
|
|
31464
|
+
if (this.boundSetupStanzaTimeout) {
|
|
31465
|
+
this.client.off('connected', this.boundSetupStanzaTimeout);
|
|
31466
|
+
this.stanzaInstance.off('raw:incoming', this.boundSetupStanzaTimeout);
|
|
31467
|
+
this.boundSetupStanzaTimeout = undefined;
|
|
31468
|
+
}
|
|
31469
|
+
}
|
|
31470
|
+
setupStanzaTimeout() {
|
|
31471
|
+
clearTimeout(this.timeoutId);
|
|
31472
|
+
this.timeoutId = setTimeout(() => {
|
|
31473
|
+
const info = {
|
|
31474
|
+
channelId: this.client.config.channelId,
|
|
31475
|
+
jid: this.stanzaInstance.jid,
|
|
31476
|
+
stanzaInstanceId: this.stanzaInstance.id,
|
|
31477
|
+
timeout: this.stanzaTimeout
|
|
31478
|
+
};
|
|
31479
|
+
this.client.logger.error('Time between XMPP stanzas exceeded timeout, disconnecting', info);
|
|
31480
|
+
this.stanzaInstance.sendStreamError({ text: 'time between stanzas exceeded timeout', condition: 'connection-timeout' });
|
|
31481
|
+
this.stop();
|
|
31482
|
+
}, this.stanzaTimeout);
|
|
31483
|
+
}
|
|
31484
|
+
}
|
|
31485
|
+
|
|
31447
31486
|
var stanza = {};
|
|
31448
31487
|
|
|
31449
31488
|
var Client$2 = {};
|
|
@@ -41444,6 +41483,7 @@ class Client extends EventEmitter {
|
|
|
41444
41483
|
this.hasMadeInitialAttempt = false;
|
|
41445
41484
|
this.http = new HttpClient();
|
|
41446
41485
|
this.reconnectOnNoLongerSubscribed = options.reconnectOnNoLongerSubscribed !== false;
|
|
41486
|
+
this.useServerSidePings = options.useServerSidePings !== false;
|
|
41447
41487
|
this.config = {
|
|
41448
41488
|
host: options.host,
|
|
41449
41489
|
apiHost: options.apiHost || options.host.replace('wss://streaming.', ''),
|
|
@@ -41576,12 +41616,13 @@ class Client extends EventEmitter {
|
|
|
41576
41616
|
};
|
|
41577
41617
|
}
|
|
41578
41618
|
handleStanzaDisconnectedEvent(disconnectedInstance) {
|
|
41579
|
-
var _a;
|
|
41619
|
+
var _a, _b;
|
|
41580
41620
|
return __awaiter$5(this, void 0, void 0, function* () {
|
|
41581
41621
|
this.logger.info('stanzaDisconnected event received', { stanzaInstanceId: disconnectedInstance.id, channelId: disconnectedInstance.channelId });
|
|
41582
41622
|
this.connected = false;
|
|
41583
41623
|
this.connecting = false;
|
|
41584
41624
|
(_a = disconnectedInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
41625
|
+
(_b = disconnectedInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
41585
41626
|
this.removeAllListeners(STANZA_DISCONNECTED);
|
|
41586
41627
|
this.removeAllListeners(NO_LONGER_SUBSCRIBED);
|
|
41587
41628
|
// unproxy events
|
|
@@ -41596,18 +41637,20 @@ class Client extends EventEmitter {
|
|
|
41596
41637
|
});
|
|
41597
41638
|
}
|
|
41598
41639
|
handleNoLongerSubscribed(stanzaInstance) {
|
|
41599
|
-
var _a;
|
|
41640
|
+
var _a, _b;
|
|
41600
41641
|
this.logger.warn('noLongerSubscribed event received', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
41601
41642
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
41643
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
41602
41644
|
this.hardReconnectRequired = true;
|
|
41603
41645
|
if (!this.reconnectOnNoLongerSubscribed) {
|
|
41604
41646
|
this.autoReconnect = false;
|
|
41605
41647
|
}
|
|
41606
41648
|
}
|
|
41607
41649
|
handleDuplicateId(stanzaInstance) {
|
|
41608
|
-
var _a;
|
|
41650
|
+
var _a, _b;
|
|
41609
41651
|
this.logger.warn('duplicate_id event received, forcing hard reconnect', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
41610
41652
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
41653
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
41611
41654
|
this.hardReconnectRequired = true;
|
|
41612
41655
|
}
|
|
41613
41656
|
disconnect() {
|
|
@@ -41816,7 +41859,7 @@ class Client extends EventEmitter {
|
|
|
41816
41859
|
});
|
|
41817
41860
|
}
|
|
41818
41861
|
makeConnectionAttempt() {
|
|
41819
|
-
var _a;
|
|
41862
|
+
var _a, _b;
|
|
41820
41863
|
return __awaiter$5(this, void 0, void 0, function* () {
|
|
41821
41864
|
if (!navigator.onLine) {
|
|
41822
41865
|
throw new OfflineError('Browser is offline, skipping connection attempt');
|
|
@@ -41840,7 +41883,7 @@ class Client extends EventEmitter {
|
|
|
41840
41883
|
extension.handleStanzaInstanceChange(stanzaInstance);
|
|
41841
41884
|
}
|
|
41842
41885
|
this.activeStanzaInstance = stanzaInstance;
|
|
41843
|
-
|
|
41886
|
+
yield this.setupConnectionMonitoring(stanzaInstance);
|
|
41844
41887
|
this.emit('connected');
|
|
41845
41888
|
}
|
|
41846
41889
|
catch (err) {
|
|
@@ -41848,6 +41891,7 @@ class Client extends EventEmitter {
|
|
|
41848
41891
|
this.logger.error('Error occurred in connection attempt, but after websocket connected. Cleaning up connection so backoff is respected', { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
41849
41892
|
this.removeStanzaBoundEventHandlers();
|
|
41850
41893
|
(_a = stanzaInstance.pinger) === null || _a === void 0 ? void 0 : _a.stop();
|
|
41894
|
+
(_b = stanzaInstance.serverMonitor) === null || _b === void 0 ? void 0 : _b.stop();
|
|
41851
41895
|
yield stanzaInstance.disconnect();
|
|
41852
41896
|
this.connected = false;
|
|
41853
41897
|
this.connecting = previousConnectingState;
|
|
@@ -41856,6 +41900,28 @@ class Client extends EventEmitter {
|
|
|
41856
41900
|
}
|
|
41857
41901
|
});
|
|
41858
41902
|
}
|
|
41903
|
+
setupConnectionMonitoring(stanzaInstance) {
|
|
41904
|
+
return __awaiter$5(this, void 0, void 0, function* () {
|
|
41905
|
+
const setupClientPinger = (message) => {
|
|
41906
|
+
const logMessage = `$(message), falling back to client-side pinging`;
|
|
41907
|
+
this.logger.warn(logMessage, { stanzaInstanceId: stanzaInstance.id, channelId: stanzaInstance.channelId });
|
|
41908
|
+
stanzaInstance.pinger = new Ping(this, stanzaInstance);
|
|
41909
|
+
};
|
|
41910
|
+
if (this.useServerSidePings) {
|
|
41911
|
+
try {
|
|
41912
|
+
// if this fails, then hawk doesn't support serverside pinging and we need to do client side pings
|
|
41913
|
+
yield stanzaInstance.subscribeToNode(this._notifications.pubsubHost, 'enable.server.side.pings');
|
|
41914
|
+
stanzaInstance.serverMonitor = new ServerMonitor(this, stanzaInstance);
|
|
41915
|
+
}
|
|
41916
|
+
catch (err) {
|
|
41917
|
+
setupClientPinger();
|
|
41918
|
+
}
|
|
41919
|
+
}
|
|
41920
|
+
else {
|
|
41921
|
+
setupClientPinger();
|
|
41922
|
+
}
|
|
41923
|
+
});
|
|
41924
|
+
}
|
|
41859
41925
|
prepareForConnect() {
|
|
41860
41926
|
return __awaiter$5(this, void 0, void 0, function* () {
|
|
41861
41927
|
if (this.config.jwt) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Client } from './client';
|
|
2
|
+
import { NamedAgent } from './types/named-agent';
|
|
3
|
+
export interface ServerMonitorOptions {
|
|
4
|
+
stanzaTimeout?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class ServerMonitor {
|
|
7
|
+
private client;
|
|
8
|
+
private stanzaInstance;
|
|
9
|
+
private stanzaTimeout;
|
|
10
|
+
private timeoutId?;
|
|
11
|
+
private boundSetupStanzaTimeout?;
|
|
12
|
+
constructor(client: Client, stanzaInstance: NamedAgent, options?: ServerMonitorOptions);
|
|
13
|
+
private start;
|
|
14
|
+
stop(): void;
|
|
15
|
+
private setupStanzaTimeout;
|
|
16
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const DEFAULT_STANZA_TIMEOUT = 70 * 1000;
|
|
3
|
+
export class ServerMonitor {
|
|
4
|
+
constructor(client, stanzaInstance, options = {}) {
|
|
5
|
+
this.client = client;
|
|
6
|
+
this.stanzaInstance = stanzaInstance;
|
|
7
|
+
this.stanzaTimeout = options.stanzaTimeout || DEFAULT_STANZA_TIMEOUT;
|
|
8
|
+
this.timeoutId = undefined;
|
|
9
|
+
this.start();
|
|
10
|
+
}
|
|
11
|
+
start() {
|
|
12
|
+
this.boundSetupStanzaTimeout = this.setupStanzaTimeout.bind(this);
|
|
13
|
+
this.client.on('connected', this.boundSetupStanzaTimeout);
|
|
14
|
+
this.stanzaInstance.on('raw:incoming', this.boundSetupStanzaTimeout);
|
|
15
|
+
}
|
|
16
|
+
stop() {
|
|
17
|
+
clearTimeout(this.timeoutId);
|
|
18
|
+
this.timeoutId = undefined;
|
|
19
|
+
if (this.boundSetupStanzaTimeout) {
|
|
20
|
+
this.client.off('connected', this.boundSetupStanzaTimeout);
|
|
21
|
+
this.stanzaInstance.off('raw:incoming', this.boundSetupStanzaTimeout);
|
|
22
|
+
this.boundSetupStanzaTimeout = undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
setupStanzaTimeout() {
|
|
26
|
+
clearTimeout(this.timeoutId);
|
|
27
|
+
this.timeoutId = setTimeout(() => {
|
|
28
|
+
const info = {
|
|
29
|
+
channelId: this.client.config.channelId,
|
|
30
|
+
jid: this.stanzaInstance.jid,
|
|
31
|
+
stanzaInstanceId: this.stanzaInstance.id,
|
|
32
|
+
timeout: this.stanzaTimeout
|
|
33
|
+
};
|
|
34
|
+
this.client.logger.error('Time between XMPP stanzas exceeded timeout, disconnecting', info);
|
|
35
|
+
this.stanzaInstance.sendStreamError({ text: 'time between stanzas exceeded timeout', condition: 'connection-timeout' });
|
|
36
|
+
this.stop();
|
|
37
|
+
}, this.stanzaTimeout);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Agent } from 'stanza';
|
|
2
2
|
import { Ping } from '../ping';
|
|
3
|
+
import { ServerMonitor } from '../server-monitor';
|
|
3
4
|
export interface NamedAgent extends Omit<Agent, 'disconnect'> {
|
|
4
5
|
id: string;
|
|
5
6
|
channelId?: string;
|
|
6
7
|
originalEmitter?: Function;
|
|
7
8
|
pinger?: Ping;
|
|
9
|
+
serverMonitor?: ServerMonitor;
|
|
8
10
|
disconnect: () => Promise<void>;
|
|
9
11
|
}
|
package/dist/npm/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
# [Unreleased](https://github.com/purecloudlabs/genesys-cloud-streaming-client/compare/v17.1.2...HEAD)
|
|
8
|
+
### Changed
|
|
9
|
+
* [PCM-2352](https://inindca.atlassian.net/browse/PCM-2352) - Use a timeout when using server-side pinging to detect when a connection has dropped
|
|
8
10
|
|
|
9
11
|
# [v17.1.2](https://github.com/purecloudlabs/genesys-cloud-streaming-client/compare/v17.1.1...v17.1.2)
|
|
10
12
|
* [NO-JIRA] - Removed Spigot testing from Jenkins build step.
|
package/dist/npm/client.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class Client extends EventEmitter {
|
|
|
16
16
|
connecting: boolean;
|
|
17
17
|
hardReconnectRequired: boolean;
|
|
18
18
|
reconnectOnNoLongerSubscribed: boolean;
|
|
19
|
+
useServerSidePings: boolean;
|
|
19
20
|
logger: Logger;
|
|
20
21
|
config: IClientConfig;
|
|
21
22
|
isGuest: boolean;
|
|
@@ -55,6 +56,7 @@ export declare class Client extends EventEmitter {
|
|
|
55
56
|
connect(connectOpts?: StreamingClientConnectOptions): Promise<void>;
|
|
56
57
|
private backoffConnectRetryHandler;
|
|
57
58
|
private makeConnectionAttempt;
|
|
59
|
+
private setupConnectionMonitoring;
|
|
58
60
|
private prepareForConnect;
|
|
59
61
|
stopServerLogging(): void;
|
|
60
62
|
startServerLogging(): void;
|