genesys-cloud-streaming-client 14.2.1-develop.21 → 14.2.1-develop.23

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.
@@ -45,6 +45,7 @@ function stanzaOptionsJwt(config) {
45
45
  }
46
46
  let wsHost = config.host.replace(/\/$/, '');
47
47
  let stanzaOptions = {
48
+ resource: config.jidResource,
48
49
  transports: {
49
50
  websocket: `${wsHost}/stream/jwt/${config.jwt}`
50
51
  },
@@ -110,16 +111,21 @@ class Client {
110
111
  originAppId: options.appId
111
112
  });
112
113
  this.on('disconnected', () => {
114
+ const wasConnected = this.connected;
113
115
  if (this._stanzaio.transport || this.connecting) {
114
- this.logger.info('disconnected event received, but reconnection is in progress');
116
+ this.logger.info('disconnected event received, but reconnection is in progress', undefined, { skipServer: !wasConnected });
115
117
  return;
116
118
  }
117
119
  this.connected = false;
118
120
  this._ping.stop();
119
- this.logger.info('Streaming client disconnected.');
121
+ // since it's possible to continually get diconnected events,
122
+ // we only want to log this if we were just connected
123
+ this.logger.info('Streaming client disconnected.', undefined, { skipServer: !wasConnected });
120
124
  const channelId = this.config.channelId;
121
125
  if (this.autoReconnect && !this.deadChannels.includes(channelId)) {
122
- this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId });
126
+ // since it's possible to continually get diconnected events,
127
+ // we only want to log this if we were just connected
128
+ this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId }, { skipServer: !wasConnected });
123
129
  this._reconnector.start();
124
130
  }
125
131
  });
@@ -197,7 +197,7 @@ class WebrtcExtension extends events_1.EventEmitter {
197
197
  this.logger.error('Failed to send stats', {
198
198
  err,
199
199
  numberOfFailedStats: statsToSend.length
200
- });
200
+ }, { skipServer: !navigator.onLine });
201
201
  }
202
202
  }
203
203
  }
@@ -17,6 +17,6 @@
17
17
  "file": "/v14/streaming-client.browser.js"
18
18
  }
19
19
  ],
20
- "build": "21",
21
- "buildDate": "2022-09-14T21:29:01.144206Z"
20
+ "build": "23",
21
+ "buildDate": "2022-09-23T17:45:10.255649Z"
22
22
  }
package/dist/es/client.js CHANGED
@@ -44,6 +44,7 @@ function stanzaOptionsJwt(config) {
44
44
  }
45
45
  let wsHost = config.host.replace(/\/$/, '');
46
46
  let stanzaOptions = {
47
+ resource: config.jidResource,
47
48
  transports: {
48
49
  websocket: `${wsHost}/stream/jwt/${config.jwt}`
49
50
  },
@@ -109,16 +110,21 @@ export class Client {
109
110
  originAppId: options.appId
110
111
  });
111
112
  this.on('disconnected', () => {
113
+ const wasConnected = this.connected;
112
114
  if (this._stanzaio.transport || this.connecting) {
113
- this.logger.info('disconnected event received, but reconnection is in progress');
115
+ this.logger.info('disconnected event received, but reconnection is in progress', undefined, { skipServer: !wasConnected });
114
116
  return;
115
117
  }
116
118
  this.connected = false;
117
119
  this._ping.stop();
118
- this.logger.info('Streaming client disconnected.');
120
+ // since it's possible to continually get diconnected events,
121
+ // we only want to log this if we were just connected
122
+ this.logger.info('Streaming client disconnected.', undefined, { skipServer: !wasConnected });
119
123
  const channelId = this.config.channelId;
120
124
  if (this.autoReconnect && !this.deadChannels.includes(channelId)) {
121
- this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId });
125
+ // since it's possible to continually get diconnected events,
126
+ // we only want to log this if we were just connected
127
+ this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId }, { skipServer: !wasConnected });
122
128
  this._reconnector.start();
123
129
  }
124
130
  });
@@ -30908,6 +30908,17 @@ var __awaiter$1 = (undefined && undefined.__awaiter) || function (thisArg, _argu
30908
30908
  step((generator = generator.apply(thisArg, _arguments || [])).next());
30909
30909
  });
30910
30910
  };
30911
+ const SAVED_REQUESTS_KEY = 'gc_logger_requests';
30912
+ const STATUS_CODES_TO_RETRY_IMMEDIATELY = [
30913
+ 408,
30914
+ 429,
30915
+ 500,
30916
+ 503,
30917
+ 504
30918
+ ];
30919
+ const STATUS_CODES_TO_RETRY_LATER = [
30920
+ 401
30921
+ ];
30911
30922
  const logUploaderMap = new Map();
30912
30923
  const getOrCreateLogUploader = (url, debugMode = false) => {
30913
30924
  let uploader = logUploaderMap.get(url);
@@ -30923,7 +30934,6 @@ class LogUploader {
30923
30934
  this.url = url;
30924
30935
  this.debugMode = debugMode;
30925
30936
  this.sendQueue = [];
30926
- this.hasPendingRequest = false;
30927
30937
  }
30928
30938
  postLogsToEndpoint(requestParams) {
30929
30939
  const deferred = getDeferred();
@@ -30932,13 +30942,44 @@ class LogUploader {
30932
30942
  this.debug('adding requestParams to sendQueue', {
30933
30943
  requestParams,
30934
30944
  updatedSendQueue: this.sendQueue.map(i => i.requestParams),
30935
- hasPendingRequest: this.hasPendingRequest
30945
+ hasPendingRequest: !!this.pendingRequest
30936
30946
  });
30937
30947
  return deferred.promise;
30938
30948
  }
30939
- postLogsToEndpointInstantly(requestParams) {
30940
- this.debug('sending request instantly', { requestParams, sendQueue: this.sendQueue.map(i => i.requestParams) });
30941
- return this.sendPostRequest(requestParams);
30949
+ postLogsToEndpointInstantly(requestParams, opts) {
30950
+ return __awaiter$1(this, void 0, void 0, function* () {
30951
+ this.debug('sending request instantly', { requestParams, sendQueue: this.sendQueue.map(i => i.requestParams) });
30952
+ if (!navigator.onLine) {
30953
+ return this.saveRequestForLater(requestParams);
30954
+ }
30955
+ try {
30956
+ yield this.sendPostRequest(requestParams);
30957
+ }
30958
+ catch (e) {
30959
+ if (opts === null || opts === void 0 ? void 0 : opts.saveOnFailure) {
30960
+ this.saveRequestForLater(requestParams);
30961
+ }
30962
+ throw e;
30963
+ }
30964
+ });
30965
+ }
30966
+ saveRequestForLater(request) {
30967
+ const savedRequests = this.getSavedRequests() || [];
30968
+ const sanitizedRequest = Object.assign({}, request);
30969
+ delete sanitizedRequest.accessToken;
30970
+ savedRequests.push(sanitizedRequest);
30971
+ window.localStorage.setItem(SAVED_REQUESTS_KEY, JSON.stringify(savedRequests));
30972
+ }
30973
+ getSavedRequests() {
30974
+ const jsonStr = window.localStorage.getItem(SAVED_REQUESTS_KEY);
30975
+ if (jsonStr) {
30976
+ try {
30977
+ return JSON.parse(jsonStr);
30978
+ }
30979
+ catch (e) {
30980
+ console.error('Failed to parse saved messages, ignoring', { savedMessagesStr: jsonStr });
30981
+ }
30982
+ }
30942
30983
  }
30943
30984
  sendEntireQueue() {
30944
30985
  this.debug('sending all queued requests instantly to clear out sendQueue', {
@@ -30948,7 +30989,7 @@ class LogUploader {
30948
30989
  let queueItem;
30949
30990
  /* eslint-disable-next-line no-cond-assign */
30950
30991
  while (queueItem = this.sendQueue.shift()) {
30951
- promises.push(this.postLogsToEndpointInstantly(queueItem.requestParams));
30992
+ promises.push(this.postLogsToEndpointInstantly(queueItem.requestParams, { saveOnFailure: true }));
30952
30993
  }
30953
30994
  /* don't want this to be async because this is called from the window 'unload' event */
30954
30995
  return promises;
@@ -30959,9 +31000,9 @@ class LogUploader {
30959
31000
  }
30960
31001
  sendNextQueuedLogToServer() {
30961
31002
  return __awaiter$1(this, void 0, void 0, function* () {
30962
- if (this.hasPendingRequest || this.sendQueue.length === 0) {
31003
+ if (this.pendingRequest || this.sendQueue.length === 0) {
30963
31004
  this.debug('sendNextQueuedLogToServer() but not sending request', {
30964
- hasPendingRequest: this.hasPendingRequest,
31005
+ hasPendingRequest: !!this.pendingRequest,
30965
31006
  sendQueueLength: this.sendQueue.length
30966
31007
  });
30967
31008
  return;
@@ -30973,15 +31014,20 @@ class LogUploader {
30973
31014
  queueItemRequestParams: queueItem.requestParams, updatedSendQueue: this.sendQueue.map(i => i.requestParams)
30974
31015
  });
30975
31016
  /* reset state and send the next item in the queue */
30976
- this.hasPendingRequest = false;
31017
+ this.pendingRequest = undefined;
30977
31018
  this.sendNextQueuedLogToServer();
30978
31019
  });
30979
- this.hasPendingRequest = true;
31020
+ this.pendingRequest = queueItem;
30980
31021
  this.debug('sending logs to server', { queueItem: queueItem.requestParams, sendQueue: this.sendQueue.map(i => i.requestParams) });
30981
31022
  // return backOff(this.sendPostRequest.bind(this, queueItem.requestParams), {
30982
- return backOff_1(() => this.sendPostRequest(queueItem.requestParams), {
31023
+ return backOff_1(() => this.backoffFn(queueItem.requestParams), {
30983
31024
  retry: (err) => {
30984
- return !!(err && err.status === 429);
31025
+ var _a;
31026
+ const status = (_a = err.response) === null || _a === void 0 ? void 0 : _a.status;
31027
+ const code = err.code;
31028
+ // we get a "ERR_NETWORK" in the case of a network blip failure. if this happens, we will want to try again.
31029
+ // this is akin to not getting a response at all
31030
+ return navigator.onLine && ((status && STATUS_CODES_TO_RETRY_IMMEDIATELY.includes(status)) || code === "ERR_NETWORK");
30985
31031
  },
30986
31032
  numOfAttempts: 10,
30987
31033
  startingDelay: 0,
@@ -30992,10 +31038,38 @@ class LogUploader {
30992
31038
  this.debug('successfully sent logs to server', { requestParams: queueItem.requestParams, response });
30993
31039
  queueItem.deferred.resolve(response);
30994
31040
  })
30995
- .catch((error) => {
30996
- this.debug('ERROR sending logs to server', { requestParams: queueItem.requestParams, error });
30997
- return queueItem.deferred.reject(error);
30998
- });
31041
+ .catch(this.handleBackoffError.bind(this, queueItem));
31042
+ });
31043
+ }
31044
+ handleBackoffError(queueItem, error) {
31045
+ var _a;
31046
+ // there are certain errors we know we don't want to try again, and certain errors/responses that *may* work in the future.
31047
+ const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
31048
+ const isRetriableStatus = status && STATUS_CODES_TO_RETRY_IMMEDIATELY.includes(status) || STATUS_CODES_TO_RETRY_LATER.includes(status);
31049
+ if (isRetriableStatus || error.code === "ERR_NETWORK") {
31050
+ this.debug('Failed to sends logs to the server, moving request to the end of the queue', { requestParams: queueItem.requestParams, error });
31051
+ this.saveRequestForLater(queueItem.requestParams);
31052
+ }
31053
+ else {
31054
+ this.debug('ERROR sending logs to server', { requestParams: queueItem.requestParams, error });
31055
+ }
31056
+ queueItem.deferred.reject(Object.assign(Object.assign({}, error), { id: "rejectionSpot1" }));
31057
+ }
31058
+ backoffFn(requestParams) {
31059
+ return __awaiter$1(this, void 0, void 0, function* () {
31060
+ const accessToken = requestParams.accessToken;
31061
+ const response = yield this.sendPostRequest(requestParams);
31062
+ // add any saved queue items to the queue using the access token
31063
+ const savedRequests = this.getSavedRequests();
31064
+ if (savedRequests) {
31065
+ window.localStorage.removeItem(SAVED_REQUESTS_KEY);
31066
+ savedRequests.map(request => {
31067
+ const reqWithToken = Object.assign({ accessToken }, request);
31068
+ // this adds it to the send queue, it doesn't send it immediately
31069
+ this.postLogsToEndpoint(reqWithToken);
31070
+ });
31071
+ }
31072
+ return response;
30999
31073
  });
31000
31074
  }
31001
31075
  sendPostRequest(requestParams) {
@@ -31132,7 +31206,7 @@ class ServerLogger {
31132
31206
  return this.logUploader.sendEntireQueue()
31133
31207
  .concat(
31134
31208
  /* this will send any items in the buffer still */
31135
- this.logBuffer.map((item) => this.logUploader.postLogsToEndpointInstantly(this.convertToRequestParams(item.traces.reverse()))));
31209
+ this.logBuffer.map((item) => this.logUploader.postLogsToEndpointInstantly(this.convertToRequestParams(item.traces.reverse()), { saveOnFailure: true })));
31136
31210
  }
31137
31211
  sendLogsToServer(immediate = false) {
31138
31212
  return __awaiter(this, void 0, void 0, function* () {
@@ -31432,7 +31506,7 @@ class Logger extends EventEmitter {
31432
31506
  }
31433
31507
  }
31434
31508
  /* eslint-disable @typescript-eslint/naming-convention */
31435
- Logger.VERSION = '4.1.1';
31509
+ Logger.VERSION = '4.2.0';
31436
31510
 
31437
31511
  /* istanbul ignore file */
31438
31512
  if (!commonjsGlobal) {
@@ -41822,7 +41896,7 @@ class WebrtcExtension extends EventEmitter {
41822
41896
  this.logger.error('Failed to send stats', {
41823
41897
  err,
41824
41898
  numberOfFailedStats: statsToSend.length
41825
- });
41899
+ }, { skipServer: !navigator.onLine });
41826
41900
  }
41827
41901
  }
41828
41902
  });
@@ -43213,6 +43287,7 @@ function stanzaOptionsJwt(config) {
43213
43287
  }
43214
43288
  let wsHost = config.host.replace(/\/$/, '');
43215
43289
  let stanzaOptions = {
43290
+ resource: config.jidResource,
43216
43291
  transports: {
43217
43292
  websocket: `${wsHost}/stream/jwt/${config.jwt}`
43218
43293
  },
@@ -43278,16 +43353,21 @@ class Client {
43278
43353
  originAppId: options.appId
43279
43354
  });
43280
43355
  this.on('disconnected', () => {
43356
+ const wasConnected = this.connected;
43281
43357
  if (this._stanzaio.transport || this.connecting) {
43282
- this.logger.info('disconnected event received, but reconnection is in progress');
43358
+ this.logger.info('disconnected event received, but reconnection is in progress', undefined, { skipServer: !wasConnected });
43283
43359
  return;
43284
43360
  }
43285
43361
  this.connected = false;
43286
43362
  this._ping.stop();
43287
- this.logger.info('Streaming client disconnected.');
43363
+ // since it's possible to continually get diconnected events,
43364
+ // we only want to log this if we were just connected
43365
+ this.logger.info('Streaming client disconnected.', undefined, { skipServer: !wasConnected });
43288
43366
  const channelId = this.config.channelId;
43289
43367
  if (this.autoReconnect && !this.deadChannels.includes(channelId)) {
43290
- this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId });
43368
+ // since it's possible to continually get diconnected events,
43369
+ // we only want to log this if we were just connected
43370
+ this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId }, { skipServer: !wasConnected });
43291
43371
  this._reconnector.start();
43292
43372
  }
43293
43373
  });
package/dist/es/webrtc.js CHANGED
@@ -195,7 +195,7 @@ export class WebrtcExtension extends EventEmitter {
195
195
  this.logger.error('Failed to send stats', {
196
196
  err,
197
197
  numberOfFailedStats: statsToSend.length
198
- });
198
+ }, { skipServer: !navigator.onLine });
199
199
  }
200
200
  }
201
201
  });
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
4
4
  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
  # [Unreleased](https://github.com/purecloudlabs/genesys-cloud-streaming-client/compare/v14.2.0...HEAD)
7
+ * [PCM-1988](https://inindca.atlassian.net/browse/PCM-1988) – Add jidResource support for jwt tokens.
8
+ * [PCM-1992](https://inindca.atlassian.net/browse/PCM-1992) – Update to the latest logger so unsent logs get preserved.
7
9
 
8
10
  ### Added
9
11
  * [PCM-1972](https://inindca.atlassian.net/browse/PCM-1972) – Added support for data channel messages if initially offered in the sdp
@@ -45,6 +45,7 @@ function stanzaOptionsJwt(config) {
45
45
  }
46
46
  let wsHost = config.host.replace(/\/$/, '');
47
47
  let stanzaOptions = {
48
+ resource: config.jidResource,
48
49
  transports: {
49
50
  websocket: `${wsHost}/stream/jwt/${config.jwt}`
50
51
  },
@@ -110,16 +111,21 @@ class Client {
110
111
  originAppId: options.appId
111
112
  });
112
113
  this.on('disconnected', () => {
114
+ const wasConnected = this.connected;
113
115
  if (this._stanzaio.transport || this.connecting) {
114
- this.logger.info('disconnected event received, but reconnection is in progress');
116
+ this.logger.info('disconnected event received, but reconnection is in progress', undefined, { skipServer: !wasConnected });
115
117
  return;
116
118
  }
117
119
  this.connected = false;
118
120
  this._ping.stop();
119
- this.logger.info('Streaming client disconnected.');
121
+ // since it's possible to continually get diconnected events,
122
+ // we only want to log this if we were just connected
123
+ this.logger.info('Streaming client disconnected.', undefined, { skipServer: !wasConnected });
120
124
  const channelId = this.config.channelId;
121
125
  if (this.autoReconnect && !this.deadChannels.includes(channelId)) {
122
- this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId });
126
+ // since it's possible to continually get diconnected events,
127
+ // we only want to log this if we were just connected
128
+ this.logger.info('Streaming client disconnected unexpectedly. Attempting to auto reconnect', { channelId }, { skipServer: !wasConnected });
123
129
  this._reconnector.start();
124
130
  }
125
131
  });
@@ -197,7 +197,7 @@ class WebrtcExtension extends events_1.EventEmitter {
197
197
  this.logger.error('Failed to send stats', {
198
198
  err,
199
199
  numberOfFailedStats: statsToSend.length
200
- });
200
+ }, { skipServer: !navigator.onLine });
201
201
  }
202
202
  }
203
203
  }