@webex/plugin-meetings 3.8.0-next.52 → 3.8.0-next.54

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.
@@ -1600,6 +1600,10 @@ export default class Meeting extends StatelessWebexPlugin {
1600
1600
  */
1601
1601
  this.#isoLocalClientMeetingJoinTime = undefined;
1602
1602
 
1603
+ // We clear the error cache of CA events on every new meeting instance
1604
+ // @ts-ignore - Fix type
1605
+ this.webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache();
1606
+
1603
1607
  /**
1604
1608
  * IP Address of the remote media server
1605
1609
  * @instance
@@ -5866,13 +5870,11 @@ export default class Meeting extends StatelessWebexPlugin {
5866
5870
  this
5867
5871
  );
5868
5872
 
5869
- const proxyError = MeetingUtil.markErrorAsHandledBySdk(error);
5870
-
5871
- joinFailed(proxyError);
5873
+ joinFailed(error);
5872
5874
 
5873
5875
  this.deferJoin = undefined;
5874
5876
 
5875
- return Promise.reject(proxyError);
5877
+ return Promise.reject(error);
5876
5878
  })
5877
5879
  .then((join) => {
5878
5880
  // @ts-ignore - config coming from registerPlugin
@@ -6255,10 +6257,10 @@ export default class Meeting extends StatelessWebexPlugin {
6255
6257
  /**
6256
6258
  * Handles ROAP_FAILURE event from the webrtc media connection
6257
6259
  *
6258
- * @param {Error} roapError
6260
+ * @param {Error} error
6259
6261
  * @returns {void}
6260
6262
  */
6261
- handleRoapFailure = (roapError) => {
6263
+ handleRoapFailure = (error) => {
6262
6264
  // eslint-disable-next-line @typescript-eslint/no-shadow
6263
6265
  const sendBehavioralMetric = (metricName, error, correlationId) => {
6264
6266
  const data = {
@@ -6274,8 +6276,6 @@ export default class Meeting extends StatelessWebexPlugin {
6274
6276
  Metrics.sendBehavioralMetric(metricName, data, metadata);
6275
6277
  };
6276
6278
 
6277
- const error = MeetingUtil.markErrorAsHandledBySdk(roapError);
6278
-
6279
6279
  if (error instanceof Errors.SdpOfferCreationError) {
6280
6280
  sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
6281
6281
 
@@ -6314,7 +6314,7 @@ export default class Meeting extends StatelessWebexPlugin {
6314
6314
  clearTimeout(this.sdpResponseTimer);
6315
6315
  this.sdpResponseTimer = undefined;
6316
6316
 
6317
- this.deferSDPAnswer.reject(error);
6317
+ this.deferSDPAnswer.reject();
6318
6318
  }
6319
6319
  } else if (error instanceof Errors.SdpError) {
6320
6320
  // this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
@@ -6478,9 +6478,7 @@ export default class Meeting extends StatelessWebexPlugin {
6478
6478
  {
6479
6479
  logText: `${LOG_HEADER} Roap Offer`,
6480
6480
  }
6481
- ).catch((originalError) => {
6482
- const error = MeetingUtil.markErrorAsHandledBySdk(originalError);
6483
-
6481
+ ).catch((error) => {
6484
6482
  const multistreamNotSupported = error instanceof MultistreamNotSupportedError;
6485
6483
 
6486
6484
  // @ts-ignore
@@ -7128,28 +7126,7 @@ export default class Meeting extends StatelessWebexPlugin {
7128
7126
  } catch (error) {
7129
7127
  const {iceConnected} = error;
7130
7128
 
7131
- let handledBySdk = false;
7132
-
7133
7129
  if (!this.hasMediaConnectionConnectedAtLeastOnce) {
7134
- const caError =
7135
- // @ts-ignore
7136
- this.webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode({
7137
- clientErrorCode: CallDiagnosticUtils.generateClientErrorCodeForIceFailure({
7138
- signalingState:
7139
- this.mediaProperties.webrtcMediaConnection?.multistreamConnection?.pc?.pc
7140
- ?.signalingState ||
7141
- this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc?.signalingState ||
7142
- 'unknown',
7143
- iceConnected,
7144
- turnServerUsed: this.turnServerUsed,
7145
- unreachable:
7146
- // @ts-ignore
7147
- await this.webex.meetings.reachability
7148
- .isWebexMediaBackendUnreachable()
7149
- .catch(() => false),
7150
- }),
7151
- });
7152
-
7153
7130
  // Only send CA event for join flow if we haven't successfully connected media yet
7154
7131
  // @ts-ignore
7155
7132
  this.webex.internal.newMetrics.submitClientEvent({
@@ -7157,25 +7134,37 @@ export default class Meeting extends StatelessWebexPlugin {
7157
7134
  payload: {
7158
7135
  canProceed: !this.turnServerUsed, // If we haven't done turn tls retry yet we will proceed with join attempt
7159
7136
  icePhase: this.addMediaData.icePhaseCallback(),
7160
- errors: [caError],
7137
+ errors: [
7138
+ // @ts-ignore
7139
+ this.webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode(
7140
+ {
7141
+ clientErrorCode: CallDiagnosticUtils.generateClientErrorCodeForIceFailure({
7142
+ signalingState:
7143
+ this.mediaProperties.webrtcMediaConnection?.multistreamConnection?.pc?.pc
7144
+ ?.signalingState ||
7145
+ this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc
7146
+ ?.signalingState ||
7147
+ 'unknown',
7148
+ iceConnected,
7149
+ turnServerUsed: this.turnServerUsed,
7150
+ unreachable:
7151
+ // @ts-ignore
7152
+ await this.webex.meetings.reachability
7153
+ .isWebexMediaBackendUnreachable()
7154
+ .catch(() => false),
7155
+ }),
7156
+ }
7157
+ ),
7158
+ ],
7161
7159
  },
7162
7160
  options: {
7163
7161
  meetingId: this.id,
7164
7162
  },
7165
7163
  });
7166
-
7167
- handledBySdk = true;
7168
7164
  }
7169
-
7170
- let timedOutError = new Error(
7165
+ throw new Error(
7171
7166
  `Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
7172
7167
  );
7173
-
7174
- if (handledBySdk) {
7175
- timedOutError = MeetingUtil.markErrorAsHandledBySdk(timedOutError);
7176
- }
7177
-
7178
- throw timedOutError;
7179
7168
  }
7180
7169
  }
7181
7170
 
@@ -7236,11 +7225,6 @@ export default class Meeting extends StatelessWebexPlugin {
7236
7225
  ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT / 1000
7237
7226
  } seconds`
7238
7227
  );
7239
-
7240
- const timeoutError = new Error('Timeout waiting for SDP answer');
7241
-
7242
- const timeoutErrorProxy = MeetingUtil.markErrorAsHandledBySdk(timeoutError);
7243
-
7244
7228
  // @ts-ignore
7245
7229
  this.webex.internal.newMetrics.submitClientEvent({
7246
7230
  name: 'client.media-engine.remote-sdp-received',
@@ -7253,7 +7237,7 @@ export default class Meeting extends StatelessWebexPlugin {
7253
7237
  }),
7254
7238
  ],
7255
7239
  },
7256
- options: {meetingId: this.id, rawError: timeoutErrorProxy},
7240
+ options: {meetingId: this.id, rawError: new Error('Timeout waiting for SDP answer')},
7257
7241
  });
7258
7242
 
7259
7243
  deferSDPAnswer.reject(new Error('Timed out waiting for REMOTE SDP ANSWER'));
@@ -7361,14 +7345,7 @@ export default class Meeting extends StatelessWebexPlugin {
7361
7345
  error
7362
7346
  );
7363
7347
 
7364
- let addMediaFailedError = new AddMediaFailed();
7365
-
7366
- // @ts-ignore - handledBySdk is added by a proxy
7367
- if (error.handledBySdk) {
7368
- addMediaFailedError = MeetingUtil.markErrorAsHandledBySdk(addMediaFailedError);
7369
- }
7370
-
7371
- throw addMediaFailedError;
7348
+ throw new AddMediaFailed();
7372
7349
  }
7373
7350
  }
7374
7351
 
@@ -6,7 +6,6 @@ import {WebexPlugin} from '@webex/webex-core';
6
6
  import {MEDIA, HTTP_VERBS, ROAP} from '../constants';
7
7
  import LoggerProxy from '../common/logs/logger-proxy';
8
8
  import {ClientMediaPreferences} from '../reachability/reachability.types';
9
- import MeetingUtil from './util';
10
9
 
11
10
  export type MediaRequestType = 'RoapMessage' | 'LocalMute';
12
11
  export type RequestResult = any;
@@ -264,9 +263,7 @@ export class LocusMediaRequest extends WebexPlugin {
264
263
 
265
264
  return result;
266
265
  })
267
- .catch((error) => {
268
- let e = error;
269
-
266
+ .catch((e) => {
270
267
  if (
271
268
  isRequestAffectingConfluenceState(request) &&
272
269
  this.confluenceState === 'creation in progress'
@@ -275,8 +272,6 @@ export class LocusMediaRequest extends WebexPlugin {
275
272
  }
276
273
 
277
274
  if (request.type === 'RoapMessage') {
278
- e = MeetingUtil.markErrorAsHandledBySdk(e);
279
-
280
275
  // @ts-ignore
281
276
  this.webex.internal.newMetrics.submitClientEvent({
282
277
  name: 'client.locus.media.response',
@@ -812,24 +812,6 @@ const MeetingUtil = {
812
812
  },
813
813
  ];
814
814
  },
815
-
816
- /**
817
- * Creates a proxy object to mark an error as handled by the SDK.
818
- * @param {Error} error original error
819
- * @returns {Proxy} proxy object with handledBySdk property
820
- */
821
- markErrorAsHandledBySdk: (error) => {
822
- return new Proxy(error, {
823
- // eslint-disable-next-line require-jsdoc
824
- get(target, prop) {
825
- if (prop === 'handledBySdk') {
826
- return true;
827
- }
828
-
829
- return Reflect.get(target, prop);
830
- },
831
- });
832
- },
833
815
  };
834
816
 
835
817
  export default MeetingUtil;
@@ -243,6 +243,7 @@ describe('plugin-meetings', () => {
243
243
  },
244
244
  });
245
245
 
246
+ webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache = sinon.stub();
246
247
  webex.internal.support.submitLogs = sinon.stub().returns(Promise.resolve());
247
248
  webex.internal.services = {get: sinon.stub().returns('locus-url')};
248
249
  webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
@@ -1012,19 +1013,13 @@ describe('plugin-meetings', () => {
1012
1013
  .stub()
1013
1014
  .returns(fakeClientError);
1014
1015
 
1015
- const promise = meeting.joinWithMedia({
1016
+ // call joinWithMedia() - it should fail
1017
+ await assert.isRejected(
1018
+ meeting.joinWithMedia({
1016
1019
  joinOptions,
1017
1020
  mediaOptions,
1018
1021
  })
1019
-
1020
- // call joinWithMedia() - it should fail
1021
- await assert.isRejected(promise);
1022
-
1023
- const rejectedError = await promise.catch((error) => error);
1024
-
1025
- // Since the SDK has sent the CA events, we need to mark this error as handled
1026
- // so the client doesn't try and send CA events again
1027
- assert.isTrue(rejectedError.handledBySdk);
1022
+ );
1028
1023
 
1029
1024
  // check the right CA events have been sent:
1030
1025
  // calls at index 0 and 2 to submitClientEvent are for "client.media.capabilities" which we don't care about in this test
@@ -1816,7 +1811,6 @@ describe('plugin-meetings', () => {
1816
1811
  await meeting.join();
1817
1812
  joinSucceeded = true;
1818
1813
  } catch (e) {
1819
- assert.isTrue(e.handledBySdk)
1820
1814
  assert.instanceOf(e, IntentToJoinError);
1821
1815
  }
1822
1816
  assert.isFalse(joinSucceeded);
@@ -1869,20 +1863,7 @@ describe('plugin-meetings', () => {
1869
1863
  });
1870
1864
  });
1871
1865
  it('should try to join the meeting and return promise reject', async () => {
1872
- await meeting.join().catch((e) => {
1873
- assert.isTrue(e.handledBySdk);
1874
- assert.calledOnce(MeetingUtil.joinMeeting);
1875
- });
1876
- });
1877
-
1878
- it('should try to join the meeting and return deferred promise reject', async () => {
1879
-
1880
- // call first
1881
- meeting.join();
1882
-
1883
- // call 2nd time will get the deferred promise
1884
- await meeting.join().catch((e) => {
1885
- assert.isTrue(e.handledBySdk);
1866
+ await meeting.join().catch(() => {
1886
1867
  assert.calledOnce(MeetingUtil.joinMeeting);
1887
1868
  });
1888
1869
  });
@@ -8832,21 +8813,14 @@ describe('plugin-meetings', () => {
8832
8813
  clock.restore();
8833
8814
  });
8834
8815
 
8835
- const checkMetricSent = (event, error, expectedErrorCode) => {
8816
+ const checkMetricSent = (event, error) => {
8836
8817
  assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
8837
- assert.deepEqual(webex.internal.newMetrics.submitClientEvent.getCall(0).args[0], {
8818
+ assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
8838
8819
  name: event,
8839
8820
  payload: {
8840
8821
  canProceed: false,
8841
8822
  },
8842
- options: {
8843
- rawError: {
8844
- ...(error.cause ? {cause: {name: error.cause.name}} : {cause: undefined}),
8845
- code: expectedErrorCode,
8846
- name: error.name,
8847
- },
8848
- meetingId: meeting.id,
8849
- },
8823
+ options: {rawError: error, meetingId: meeting.id},
8850
8824
  });
8851
8825
  };
8852
8826
 
@@ -8880,7 +8854,7 @@ describe('plugin-meetings', () => {
8880
8854
 
8881
8855
  eventListeners[MediaConnectionEventNames.ROAP_FAILURE](fakeError);
8882
8856
 
8883
- checkMetricSent('client.media-engine.local-sdp-generated', fakeError, 30005);
8857
+ checkMetricSent('client.media-engine.local-sdp-generated', fakeError);
8884
8858
  checkBehavioralMetricSent(
8885
8859
  BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
8886
8860
  Errors.ErrorCode.SdpOfferCreationError,
@@ -8897,7 +8871,7 @@ describe('plugin-meetings', () => {
8897
8871
 
8898
8872
  eventListeners[MediaConnectionEventNames.ROAP_FAILURE](fakeError);
8899
8873
 
8900
- checkMetricSent('client.media-engine.remote-sdp-received', fakeError, 30006);
8874
+ checkMetricSent('client.media-engine.remote-sdp-received', fakeError);
8901
8875
  checkBehavioralMetricSent(
8902
8876
  BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
8903
8877
  Errors.ErrorCode.SdpOfferHandlingError,
@@ -8921,7 +8895,7 @@ describe('plugin-meetings', () => {
8921
8895
 
8922
8896
  eventListeners[MediaConnectionEventNames.ROAP_FAILURE](fakeError);
8923
8897
 
8924
- checkMetricSent('client.media-engine.remote-sdp-received', fakeError, 30004);
8898
+ checkMetricSent('client.media-engine.remote-sdp-received', fakeError);
8925
8899
  checkBehavioralMetricSent(
8926
8900
  BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
8927
8901
  Errors.ErrorCode.SdpAnswerHandlingError,
@@ -8929,7 +8903,6 @@ describe('plugin-meetings', () => {
8929
8903
  fakeRootCauseName
8930
8904
  );
8931
8905
  assert.calledOnce(meeting.deferSDPAnswer.reject);
8932
- assert.isTrue(meeting.deferSDPAnswer.reject.getCall(0).args[0].handledBySdk);
8933
8906
  assert.calledOnce(clearTimeoutSpy);
8934
8907
  });
8935
8908
 
@@ -8939,7 +8912,7 @@ describe('plugin-meetings', () => {
8939
8912
 
8940
8913
  eventListeners[MediaConnectionEventNames.ROAP_FAILURE](fakeError);
8941
8914
 
8942
- checkMetricSent('client.media-engine.local-sdp-generated', fakeError, 30002);
8915
+ checkMetricSent('client.media-engine.local-sdp-generated', fakeError);
8943
8916
  // expectedMetadataType is the error name in this case
8944
8917
  checkBehavioralMetricSent(
8945
8918
  BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
@@ -8957,7 +8930,7 @@ describe('plugin-meetings', () => {
8957
8930
 
8958
8931
  eventListeners[MediaConnectionEventNames.ROAP_FAILURE](fakeError);
8959
8932
 
8960
- checkMetricSent('client.media-engine.local-sdp-generated', fakeError, 30003);
8933
+ checkMetricSent('client.media-engine.local-sdp-generated', fakeError);
8961
8934
  // expectedMetadataType is the error name in this case
8962
8935
  checkBehavioralMetricSent(
8963
8936
  BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
@@ -9151,7 +9124,7 @@ describe('plugin-meetings', () => {
9151
9124
  assert.calledOnceWithExactly(getErrorPayloadForClientErrorCodeStub, {
9152
9125
  clientErrorCode: expectedErrorCode,
9153
9126
  });
9154
- assert.deepEqual(webex.internal.newMetrics.submitClientEvent.getCall(0).args[0], {
9127
+ assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
9155
9128
  name: 'client.media-engine.remote-sdp-received',
9156
9129
  payload: {
9157
9130
  canProceed,
@@ -9159,18 +9132,9 @@ describe('plugin-meetings', () => {
9159
9132
  },
9160
9133
  options: {
9161
9134
  meetingId: meeting.id,
9162
- rawError: fakeError instanceof MultistreamNotSupportedError ? {
9163
- code: fakeError.code,
9164
- name: fakeError.name,
9165
- sdkMessage: fakeError.sdkMessage,
9166
- error: fakeError.error,
9167
- } : {},
9135
+ rawError: fakeError,
9168
9136
  },
9169
9137
  });
9170
- const actualError = webex.internal.newMetrics.submitClientEvent.getCall(0).args[0].options.rawError;
9171
-
9172
- assert.isTrue(actualError.handledBySdk);
9173
- assert.equal(actualError.message, fakeError.message);
9174
9138
  };
9175
9139
 
9176
9140
  it('handles OFFER message correctly when request fails', async () => {
@@ -185,12 +185,7 @@ describe('LocusMediaRequest.send()', () => {
185
185
 
186
186
  it('sends correct metric event when roap message fails', async () => {
187
187
  webexRequestStub.rejects({code: 300, message: 'fake error'});
188
-
189
- const promise = sendRoapMessage('OFFER');
190
- await assert.isRejected(promise);
191
-
192
- const error = await promise.catch((err) => err);
193
- assert.isTrue(error.handledBySdk);
188
+ await assert.isRejected(sendRoapMessage('OFFER'));
194
189
 
195
190
  assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
196
191
  name: 'client.locus.media.response',
@@ -1185,14 +1185,6 @@ describe('plugin-meetings', () => {
1185
1185
  });
1186
1186
  });
1187
1187
 
1188
- describe('markErrorAsHandledBySdk', () => {
1189
- it('should set the error as handled', () => {
1190
- const error = MeetingUtil.markErrorAsHandledBySdk(new Error('Test error'));
1191
-
1192
- assert.isTrue(error.handledBySdk);
1193
- })
1194
- });
1195
-
1196
1188
  describe('getChangeMeetingFloorErrorPayload', () => {
1197
1189
  [
1198
1190
  {
@@ -182,6 +182,15 @@ describe('plugin-meetings', () => {
182
182
  metrics: {
183
183
  submitClientMetrics: sinon.stub().returns(Promise.resolve()),
184
184
  },
185
+ newMetrics: {
186
+ submitClientEvent: sinon.stub(),
187
+ callDiagnosticLatencies: {
188
+ measureLatency: sinon.stub().returns(Promise.resolve()),
189
+ },
190
+ callDiagnosticMetrics: {
191
+ clearErrorCache: sinon.stub(),
192
+ },
193
+ },
185
194
  });
186
195
  webex.emit('ready');
187
196
  });