@webex/plugin-meetings 3.12.0-next.22 → 3.12.0-next.24
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/aiEnableRequest/index.js +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/interceptors/locusRetry.js +23 -8
- package/dist/interceptors/locusRetry.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +1 -2
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meetings/index.js +8 -8
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +18 -3
- package/dist/meetings/util.js.map +1 -1
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/interceptors/locusRetry.d.ts +4 -4
- package/dist/webinar/index.js +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -0
- package/src/interceptors/locusRetry.ts +25 -4
- package/src/locus-info/index.ts +1 -1
- package/src/meetings/index.ts +2 -2
- package/src/meetings/util.ts +18 -0
- package/test/unit/spec/interceptors/locusRetry.ts +205 -4
- package/test/unit/spec/locus-info/index.js +8 -33
- package/test/unit/spec/meetings/index.js +27 -0
- package/test/unit/spec/meetings/utils.js +16 -0
package/dist/meetings/util.js
CHANGED
|
@@ -274,6 +274,21 @@ MeetingsUtil.getThisDevice = function (newLocus, deviceUrl) {
|
|
|
274
274
|
return null;
|
|
275
275
|
};
|
|
276
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Checks if the self state in a locus indicates a breakout move or breakout end.
|
|
279
|
+
* Returns true when:
|
|
280
|
+
* - self state is LEFT with reason MOVED (regular breakout move), OR
|
|
281
|
+
* - fullState is INACTIVE with endMeetingReason BREAKOUT_ENDED (breakout session ended)
|
|
282
|
+
* @param {Object} locus locus data
|
|
283
|
+
* @returns {boolean}
|
|
284
|
+
*/
|
|
285
|
+
MeetingsUtil.isSelfMovedOrBreakoutEnded = function (locus) {
|
|
286
|
+
var _locus$self, _locus$self2, _locus$fullState, _locus$fullState2;
|
|
287
|
+
var isSelfLeftMoved = (locus === null || locus === void 0 ? void 0 : (_locus$self = locus.self) === null || _locus$self === void 0 ? void 0 : _locus$self.state) === _constants._LEFT_ && (locus === null || locus === void 0 ? void 0 : (_locus$self2 = locus.self) === null || _locus$self2 === void 0 ? void 0 : _locus$self2.reason) === _constants._MOVED_;
|
|
288
|
+
var isBreakoutEnded = (locus === null || locus === void 0 ? void 0 : (_locus$fullState = locus.fullState) === null || _locus$fullState === void 0 ? void 0 : _locus$fullState.state) === _constants.LOCUS.STATE.INACTIVE && (locus === null || locus === void 0 ? void 0 : (_locus$fullState2 = locus.fullState) === null || _locus$fullState2 === void 0 ? void 0 : _locus$fullState2.endMeetingReason) === _constants._BREAKOUT_ENDED_;
|
|
289
|
+
return isSelfLeftMoved || isBreakoutEnded;
|
|
290
|
+
};
|
|
291
|
+
|
|
277
292
|
/**
|
|
278
293
|
* get self device joined status from locus data
|
|
279
294
|
* @param {Object} meeting current meeting data
|
|
@@ -309,10 +324,10 @@ MeetingsUtil.isBreakoutLocusDTO = function (newLocus) {
|
|
|
309
324
|
* @private
|
|
310
325
|
*/
|
|
311
326
|
MeetingsUtil.isValidBreakoutLocus = function (locus) {
|
|
312
|
-
var _locus$
|
|
313
|
-
var inActiveStatus = (locus === null || locus === void 0 ? void 0 : (_locus$
|
|
327
|
+
var _locus$fullState3, _locus$self3;
|
|
328
|
+
var inActiveStatus = (locus === null || locus === void 0 ? void 0 : (_locus$fullState3 = locus.fullState) === null || _locus$fullState3 === void 0 ? void 0 : _locus$fullState3.state) === _constants.LOCUS.STATE.INACTIVE;
|
|
314
329
|
var isLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(locus);
|
|
315
|
-
var selfJoined = ((_locus$
|
|
330
|
+
var selfJoined = ((_locus$self3 = locus.self) === null || _locus$self3 === void 0 ? void 0 : _locus$self3.state) === _constants._JOINED_;
|
|
316
331
|
return isLocusAsBreakout && !inActiveStatus && selfJoined;
|
|
317
332
|
};
|
|
318
333
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_constants","require","_loggerProxy","_interopRequireDefault","_triggerProxy","_constants2","_metrics","_meetings","MeetingsUtil","getMeetingAddedType","type","DESTINATION_TYPE","LOCUS_ID","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","MEETING_KEY","CORRELATION_ID","correlationId","_data$message","message","seq","messageType","tieBreaker","errorType","errorCause","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ROAP_MERCURY_EVENT_RECEIVED","correlation_id","message_type","error_type","error_cause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","_data$message$sdps","roapMessage","sdp","sdps","length","undefined","roapMessageReceived","getMediaServer","mediaServer","split","find","line","startsWith","shift","replace","toLowerCase","_unused","getMediaServerIp","mediaServerIp","_sdp$split$find$match","match","trim","_unused2","getCorrelationIdForDevice","deviceUrl","locusSelf","devices","foundDevice","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","_userPreferences$site","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","_asyncToGenerator2","_regenerator","mark","_callee","hasCodec","pc","offer","_t","wrap","_context","prev","next","window","RTCPeerConnection","createOffer","offerToReceiveVideo","sent","close","LoggerProxy","logger","warn","abrupt","stop","checkH264Support","_checkH264Support","_callee2","options","_this","_ref2","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","_context2","_now","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call","_x","apply","arguments","getThisDevice","newLocus","_newLocus$self","_newLocus$self$device","self","joinedOnThisDevice","thisDevice","state","_JOINED_","_LEFT_","reason","_MOVED_","isBreakoutLocusDTO","_newLocus$controls","_newLocus$controls$br","_newLocus$info","controls","breakout","sessionType","BREAKOUTS","SESSION_TYPES","BREAKOUT","info","isBreakout","isValidBreakoutLocus","locus","_locus$fullState","_locus$self","inActiveStatus","fullState","LOCUS","STATE","INACTIVE","isLocusAsBreakout","selfJoined","isMainAssociatedWithBreakout","mainLocus","breakoutLocus","_mainLocus$controls","_mainLocus$controls$b","_mainLocus$controls2","_mainLocus$controls2$","_breakoutLocus$contro","_breakoutLocus$contro2","_breakoutLocus$self","_MeetingsUtil$getThis","_MeetingsUtil$getThis2","replaceInfo","replaces","locusUrl","_default","exports"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _CREATED_,\n _INCOMING_,\n _JOINED_,\n _LEFT_,\n DESTINATION_TYPE,\n _MOVED_,\n BREAKOUTS,\n EVENT_TRIGGERS,\n LOCUS,\n LOCUSEVENT,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport Metrics from '../metrics';\nimport {MEETING_KEY} from './meetings.types';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type: DESTINATION_TYPE) =>\n type === DESTINATION_TYPE.LOCUS_ID ? _INCOMING_ : _CREATED_;\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(MEETING_KEY.CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_MERCURY_EVENT_RECEIVED, {\n correlation_id: data.correlationId,\n seq,\n message_type: messageType,\n error_type: errorType,\n error_cause: errorCause,\n });\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message, 'from mercury');\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n meeting.roapMessageReceived(roapMessage);\n }\n }\n }\n};\n\nMeetingsUtil.getMediaServer = (sdp) => {\n let mediaServer;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServer = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .split(' ')\n .shift()\n .replace('o=', '')\n .toLowerCase();\n } catch {\n mediaServer = undefined;\n }\n\n return mediaServer;\n};\n\nMeetingsUtil.getMediaServerIp = (sdp) => {\n let mediaServerIp;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServerIp = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .match(/o=\\S+ \\d+ \\d+ IN IP4 ([\\d.]+)/)?.[1]\n .toLowerCase()\n .trim();\n } catch {\n mediaServerIp = undefined;\n }\n\n return mediaServerIp;\n};\n\n/**\n * Finds correlationId of a device from locus self devices array\n * that matches the given deviceUrl\n * @param {string} deviceUrl\n * @param {object} locusSelf\n * @returns {string|false} correlationId or false if not found\n */\nMeetingsUtil.getCorrelationIdForDevice = (deviceUrl: string, locusSelf: any) => {\n if (locusSelf?.devices) {\n const foundDevice = locusSelf?.devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences?.sites?.length) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n } else {\n result = userPreferences.sites[0].siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\n/**\n * get device from locus data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {\n if (newLocus?.self?.devices?.length > 0) {\n return newLocus.self.devices.find((device) => device.url === deviceUrl);\n }\n\n return null;\n};\n\n/**\n * get self device joined status from locus data\n * @param {Object} meeting current meeting data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.joinedOnThisDevice = (meeting: any, newLocus: any, deviceUrl: string) => {\n const thisDevice = MeetingsUtil.getThisDevice(newLocus, deviceUrl);\n if (thisDevice) {\n if (!thisDevice.correlationId || meeting?.correlationId === thisDevice.correlationId) {\n return (\n thisDevice.state === _JOINED_ ||\n (thisDevice.state === _LEFT_ && thisDevice.reason === _MOVED_)\n );\n }\n }\n\n return false;\n};\n\n/**\n * check the new locus is breakout session's one or not\n * @param {Object} newLocus new locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isBreakoutLocusDTO = (newLocus: any) => {\n return (\n newLocus?.controls?.breakout?.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT ||\n !!newLocus?.info?.isBreakout\n );\n};\n\n/**\n * check the locus is valid breakout locus or not\n * @param {Object} locus\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isValidBreakoutLocus = (locus: any) => {\n const inActiveStatus = locus?.fullState?.state === LOCUS.STATE.INACTIVE;\n const isLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(locus);\n const selfJoined = locus.self?.state === _JOINED_;\n\n return isLocusAsBreakout && !inActiveStatus && selfJoined;\n};\n/**\n * check if the breakout locus is associated with the main locus by comparing the breakout control url or the replaces info in self device\n * @param {Object} mainLocus main locus data\n * @param {Object} breakoutLocus breakout locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isMainAssociatedWithBreakout = (mainLocus: any, breakoutLocus: any) => {\n if (\n mainLocus.controls?.breakout?.url &&\n mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url\n ) {\n return true;\n }\n const deviceUrl = breakoutLocus?.self?.deviceUrl;\n const replaceInfo = MeetingsUtil.getThisDevice(breakoutLocus, deviceUrl)?.replaces?.[0];\n if (replaceInfo?.locusUrl && replaceInfo.locusUrl === mainLocus.url) {\n return true;\n }\n\n return false;\n};\nexport default MeetingsUtil;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_constants","require","_loggerProxy","_interopRequireDefault","_triggerProxy","_constants2","_metrics","_meetings","MeetingsUtil","getMeetingAddedType","type","DESTINATION_TYPE","LOCUS_ID","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","MEETING_KEY","CORRELATION_ID","correlationId","_data$message","message","seq","messageType","tieBreaker","errorType","errorCause","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ROAP_MERCURY_EVENT_RECEIVED","correlation_id","message_type","error_type","error_cause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","_data$message$sdps","roapMessage","sdp","sdps","length","undefined","roapMessageReceived","getMediaServer","mediaServer","split","find","line","startsWith","shift","replace","toLowerCase","_unused","getMediaServerIp","mediaServerIp","_sdp$split$find$match","match","trim","_unused2","getCorrelationIdForDevice","deviceUrl","locusSelf","devices","foundDevice","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","_userPreferences$site","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","_asyncToGenerator2","_regenerator","mark","_callee","hasCodec","pc","offer","_t","wrap","_context","prev","next","window","RTCPeerConnection","createOffer","offerToReceiveVideo","sent","close","LoggerProxy","logger","warn","abrupt","stop","checkH264Support","_checkH264Support","_callee2","options","_this","_ref2","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","_context2","_now","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call","_x","apply","arguments","getThisDevice","newLocus","_newLocus$self","_newLocus$self$device","self","isSelfMovedOrBreakoutEnded","locus","_locus$self","_locus$self2","_locus$fullState","_locus$fullState2","isSelfLeftMoved","state","_LEFT_","reason","_MOVED_","isBreakoutEnded","fullState","LOCUS","STATE","INACTIVE","endMeetingReason","_BREAKOUT_ENDED_","joinedOnThisDevice","thisDevice","_JOINED_","isBreakoutLocusDTO","_newLocus$controls","_newLocus$controls$br","_newLocus$info","controls","breakout","sessionType","BREAKOUTS","SESSION_TYPES","BREAKOUT","info","isBreakout","isValidBreakoutLocus","_locus$fullState3","_locus$self3","inActiveStatus","isLocusAsBreakout","selfJoined","isMainAssociatedWithBreakout","mainLocus","breakoutLocus","_mainLocus$controls","_mainLocus$controls$b","_mainLocus$controls2","_mainLocus$controls2$","_breakoutLocus$contro","_breakoutLocus$contro2","_breakoutLocus$self","_MeetingsUtil$getThis","_MeetingsUtil$getThis2","replaceInfo","replaces","locusUrl","_default","exports"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _CREATED_,\n _INCOMING_,\n _JOINED_,\n _LEFT_,\n DESTINATION_TYPE,\n _MOVED_,\n _BREAKOUT_ENDED_,\n BREAKOUTS,\n EVENT_TRIGGERS,\n LOCUS,\n LOCUSEVENT,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport Metrics from '../metrics';\nimport {MEETING_KEY} from './meetings.types';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type: DESTINATION_TYPE) =>\n type === DESTINATION_TYPE.LOCUS_ID ? _INCOMING_ : _CREATED_;\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(MEETING_KEY.CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_MERCURY_EVENT_RECEIVED, {\n correlation_id: data.correlationId,\n seq,\n message_type: messageType,\n error_type: errorType,\n error_cause: errorCause,\n });\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message, 'from mercury');\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n meeting.roapMessageReceived(roapMessage);\n }\n }\n }\n};\n\nMeetingsUtil.getMediaServer = (sdp) => {\n let mediaServer;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServer = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .split(' ')\n .shift()\n .replace('o=', '')\n .toLowerCase();\n } catch {\n mediaServer = undefined;\n }\n\n return mediaServer;\n};\n\nMeetingsUtil.getMediaServerIp = (sdp) => {\n let mediaServerIp;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServerIp = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .match(/o=\\S+ \\d+ \\d+ IN IP4 ([\\d.]+)/)?.[1]\n .toLowerCase()\n .trim();\n } catch {\n mediaServerIp = undefined;\n }\n\n return mediaServerIp;\n};\n\n/**\n * Finds correlationId of a device from locus self devices array\n * that matches the given deviceUrl\n * @param {string} deviceUrl\n * @param {object} locusSelf\n * @returns {string|false} correlationId or false if not found\n */\nMeetingsUtil.getCorrelationIdForDevice = (deviceUrl: string, locusSelf: any) => {\n if (locusSelf?.devices) {\n const foundDevice = locusSelf?.devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences?.sites?.length) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n } else {\n result = userPreferences.sites[0].siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\n/**\n * get device from locus data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {\n if (newLocus?.self?.devices?.length > 0) {\n return newLocus.self.devices.find((device) => device.url === deviceUrl);\n }\n\n return null;\n};\n\n/**\n * Checks if the self state in a locus indicates a breakout move or breakout end.\n * Returns true when:\n * - self state is LEFT with reason MOVED (regular breakout move), OR\n * - fullState is INACTIVE with endMeetingReason BREAKOUT_ENDED (breakout session ended)\n * @param {Object} locus locus data\n * @returns {boolean}\n */\nMeetingsUtil.isSelfMovedOrBreakoutEnded = (locus: any): boolean => {\n const isSelfLeftMoved = locus?.self?.state === _LEFT_ && locus?.self?.reason === _MOVED_;\n const isBreakoutEnded =\n locus?.fullState?.state === LOCUS.STATE.INACTIVE &&\n locus?.fullState?.endMeetingReason === _BREAKOUT_ENDED_;\n\n return isSelfLeftMoved || isBreakoutEnded;\n};\n\n/**\n * get self device joined status from locus data\n * @param {Object} meeting current meeting data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.joinedOnThisDevice = (meeting: any, newLocus: any, deviceUrl: string) => {\n const thisDevice = MeetingsUtil.getThisDevice(newLocus, deviceUrl);\n if (thisDevice) {\n if (!thisDevice.correlationId || meeting?.correlationId === thisDevice.correlationId) {\n return (\n thisDevice.state === _JOINED_ ||\n (thisDevice.state === _LEFT_ && thisDevice.reason === _MOVED_)\n );\n }\n }\n\n return false;\n};\n\n/**\n * check the new locus is breakout session's one or not\n * @param {Object} newLocus new locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isBreakoutLocusDTO = (newLocus: any) => {\n return (\n newLocus?.controls?.breakout?.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT ||\n !!newLocus?.info?.isBreakout\n );\n};\n\n/**\n * check the locus is valid breakout locus or not\n * @param {Object} locus\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isValidBreakoutLocus = (locus: any) => {\n const inActiveStatus = locus?.fullState?.state === LOCUS.STATE.INACTIVE;\n const isLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(locus);\n const selfJoined = locus.self?.state === _JOINED_;\n\n return isLocusAsBreakout && !inActiveStatus && selfJoined;\n};\n/**\n * check if the breakout locus is associated with the main locus by comparing the breakout control url or the replaces info in self device\n * @param {Object} mainLocus main locus data\n * @param {Object} breakoutLocus breakout locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isMainAssociatedWithBreakout = (mainLocus: any, breakoutLocus: any) => {\n if (\n mainLocus.controls?.breakout?.url &&\n mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url\n ) {\n return true;\n }\n const deviceUrl = breakoutLocus?.self?.deviceUrl;\n const replaceInfo = MeetingsUtil.getThisDevice(breakoutLocus, deviceUrl)?.replaces?.[0];\n if (replaceInfo?.locusUrl && replaceInfo.locusUrl === mainLocus.url) {\n return true;\n }\n\n return false;\n};\nexport default MeetingsUtil;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -73,6 +73,7 @@ export declare const _JOINED_ = "JOINED";
|
|
|
73
73
|
export declare const _LOCUS_ID_ = "LOCUS_ID";
|
|
74
74
|
export declare const _LEFT_ = "LEFT";
|
|
75
75
|
export declare const _MOVED_ = "MOVED";
|
|
76
|
+
export declare const _BREAKOUT_ENDED_ = "BREAKOUT_ENDED";
|
|
76
77
|
export declare const _ON_HOLD_LOBBY_ = "ON_HOLD_LOBBY";
|
|
77
78
|
export declare const _MEETING_LINK_ = "MEETING_LINK";
|
|
78
79
|
export declare const _MEETING_UUID_ = "MEETING_UUID";
|
|
@@ -11,11 +11,11 @@ export default class LocusRetryStatusInterceptor extends Interceptor {
|
|
|
11
11
|
*/
|
|
12
12
|
static create(): LocusRetryStatusInterceptor;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
* @param {
|
|
16
|
-
* @
|
|
17
|
-
* @returns {Promise<WebexHttpError>}
|
|
14
|
+
* Check whether a URI is a Locus /hashtree or /sync endpoint.
|
|
15
|
+
* @param {string} uri
|
|
16
|
+
* @returns {boolean}
|
|
18
17
|
*/
|
|
18
|
+
private static isLocusHashtreeOrSync;
|
|
19
19
|
onResponseError(options: any, reason: any): Promise<unknown>;
|
|
20
20
|
/**
|
|
21
21
|
* Handle retries for locus service unavailable errors
|
package/dist/webinar/index.js
CHANGED
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -103,6 +103,7 @@ export const _JOINED_ = 'JOINED';
|
|
|
103
103
|
export const _LOCUS_ID_ = 'LOCUS_ID';
|
|
104
104
|
export const _LEFT_ = 'LEFT';
|
|
105
105
|
export const _MOVED_ = 'MOVED';
|
|
106
|
+
export const _BREAKOUT_ENDED_ = 'BREAKOUT_ENDED';
|
|
106
107
|
export const _ON_HOLD_LOBBY_ = 'ON_HOLD_LOBBY';
|
|
107
108
|
export const _MEETING_LINK_ = 'MEETING_LINK';
|
|
108
109
|
export const _MEETING_UUID_ = 'MEETING_UUID';
|
|
@@ -18,12 +18,33 @@ export default class LocusRetryStatusInterceptor extends Interceptor {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @param {
|
|
23
|
-
* @
|
|
24
|
-
* @returns {Promise<WebexHttpError>}
|
|
21
|
+
* Check whether a URI is a Locus /hashtree or /sync endpoint.
|
|
22
|
+
* @param {string} uri
|
|
23
|
+
* @returns {boolean}
|
|
25
24
|
*/
|
|
25
|
+
private static isLocusHashtreeOrSync(uri: string): boolean {
|
|
26
|
+
try {
|
|
27
|
+
const {pathname} = new URL(uri);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
pathname.includes('/locus/') &&
|
|
31
|
+
(pathname.endsWith('/hashtree') || pathname.endsWith('/sync'))
|
|
32
|
+
);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
onResponseError(options, reason) {
|
|
39
|
+
// Don't retry /hashtree or /sync calls for 429 or any 5xx — during a sync storm retries
|
|
40
|
+
// make things worse. The normal sync timers will handle recovery for these endpoints.
|
|
41
|
+
if (
|
|
42
|
+
(reason.statusCode === 429 || reason.statusCode >= 500) &&
|
|
43
|
+
LocusRetryStatusInterceptor.isLocusHashtreeOrSync(options.uri)
|
|
44
|
+
) {
|
|
45
|
+
return Promise.reject(reason);
|
|
46
|
+
}
|
|
47
|
+
|
|
27
48
|
if ((reason.statusCode === 503 || reason.statusCode === 429) && options.uri.includes('locus')) {
|
|
28
49
|
const hasRetriedLocusRequest = rateLimitExpiryTime.get(this);
|
|
29
50
|
const retryAfterTime = options.headers['retry-after'] || 2000;
|
package/src/locus-info/index.ts
CHANGED
|
@@ -1635,7 +1635,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1635
1635
|
* @memberof LocusInfo
|
|
1636
1636
|
*/
|
|
1637
1637
|
updateLocusInfo(locus) {
|
|
1638
|
-
if (
|
|
1638
|
+
if (MeetingsUtil.isSelfMovedOrBreakoutEnded(locus)) {
|
|
1639
1639
|
// When moved to a breakout session locus sends a message for the previous locus
|
|
1640
1640
|
// indicating that we have been moved. It isn't helpful to continue parsing this
|
|
1641
1641
|
// as it gets interpreted as if we have left the call
|
package/src/meetings/index.ts
CHANGED
|
@@ -315,7 +315,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
315
315
|
const breakoutLocus = this.meetingCollection.getActiveBreakoutLocus(breakoutUrl);
|
|
316
316
|
|
|
317
317
|
const isSelfJoined = newLocus?.self?.state === _JOINED_;
|
|
318
|
-
const isSelfMoved = newLocus
|
|
318
|
+
const isSelfMoved = MeetingsUtil.isSelfMovedOrBreakoutEnded(newLocus);
|
|
319
319
|
// @ts-ignore
|
|
320
320
|
const deviceFromNewLocus = MeetingsUtil.getThisDevice(newLocus, this.webex.internal.device.url);
|
|
321
321
|
const isResourceMovedOnThisDevice =
|
|
@@ -392,7 +392,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
392
392
|
private isNeedHandleLocusDTO(meeting: any, newLocus: any) {
|
|
393
393
|
if (newLocus) {
|
|
394
394
|
const isNewLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(newLocus);
|
|
395
|
-
const isSelfMoved = newLocus
|
|
395
|
+
const isSelfMoved = MeetingsUtil.isSelfMovedOrBreakoutEnded(newLocus);
|
|
396
396
|
const isSelfMovedToLobby =
|
|
397
397
|
newLocus?.self?.devices[0]?.intent?.reason === _ON_HOLD_LOBBY_ &&
|
|
398
398
|
newLocus?.self?.devices[0]?.intent?.type === _WAIT_;
|
package/src/meetings/util.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
_LEFT_,
|
|
8
8
|
DESTINATION_TYPE,
|
|
9
9
|
_MOVED_,
|
|
10
|
+
_BREAKOUT_ENDED_,
|
|
10
11
|
BREAKOUTS,
|
|
11
12
|
EVENT_TRIGGERS,
|
|
12
13
|
LOCUS,
|
|
@@ -266,6 +267,23 @@ MeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {
|
|
|
266
267
|
return null;
|
|
267
268
|
};
|
|
268
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Checks if the self state in a locus indicates a breakout move or breakout end.
|
|
272
|
+
* Returns true when:
|
|
273
|
+
* - self state is LEFT with reason MOVED (regular breakout move), OR
|
|
274
|
+
* - fullState is INACTIVE with endMeetingReason BREAKOUT_ENDED (breakout session ended)
|
|
275
|
+
* @param {Object} locus locus data
|
|
276
|
+
* @returns {boolean}
|
|
277
|
+
*/
|
|
278
|
+
MeetingsUtil.isSelfMovedOrBreakoutEnded = (locus: any): boolean => {
|
|
279
|
+
const isSelfLeftMoved = locus?.self?.state === _LEFT_ && locus?.self?.reason === _MOVED_;
|
|
280
|
+
const isBreakoutEnded =
|
|
281
|
+
locus?.fullState?.state === LOCUS.STATE.INACTIVE &&
|
|
282
|
+
locus?.fullState?.endMeetingReason === _BREAKOUT_ENDED_;
|
|
283
|
+
|
|
284
|
+
return isSelfLeftMoved || isBreakoutEnded;
|
|
285
|
+
};
|
|
286
|
+
|
|
269
287
|
/**
|
|
270
288
|
* get self device joined status from locus data
|
|
271
289
|
* @param {Object} meeting current meeting data
|
|
@@ -36,6 +36,27 @@ describe('plugin-meetings', () => {
|
|
|
36
36
|
uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
|
|
37
37
|
body: 'foo'
|
|
38
38
|
};
|
|
39
|
+
|
|
40
|
+
const hashTreeOptions = {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
headers: {
|
|
43
|
+
trackingid: 'test',
|
|
44
|
+
'retry-after': 1000,
|
|
45
|
+
},
|
|
46
|
+
uri: `https://locus-test.webex.com/locus/api/v1/loci/12345/session/abc/datasets/main/hashtree`,
|
|
47
|
+
body: undefined,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const syncOptions = {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
trackingid: 'test',
|
|
54
|
+
'retry-after': 1000,
|
|
55
|
+
},
|
|
56
|
+
uri: `https://locus-test.webex.com/locus/api/v1/loci/12345/session/abc/datasets/main/sync`,
|
|
57
|
+
body: 'foo',
|
|
58
|
+
};
|
|
59
|
+
|
|
39
60
|
const reason1 = new WebexHttpError.MethodNotAllowed({
|
|
40
61
|
statusCode: 403,
|
|
41
62
|
options: {
|
|
@@ -68,14 +89,194 @@ describe('plugin-meetings', () => {
|
|
|
68
89
|
});
|
|
69
90
|
|
|
70
91
|
it('calls handleRetryRequestLocusServiceError with correct retry time when locus service unavailable error', () => {
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
interceptor.webex.request = sinon.stub().returns(Promise.resolve());
|
|
93
|
+
const handleRetryStub = sinon.stub(
|
|
94
|
+
interceptor,
|
|
95
|
+
'handleRetryRequestLocusServiceError'
|
|
96
|
+
);
|
|
97
|
+
handleRetryStub.returns(Promise.resolve());
|
|
98
|
+
|
|
99
|
+
return interceptor.onResponseError(options, reason2).then(() => {
|
|
100
|
+
expect(handleRetryStub.calledWith(options, 1000)).to.be.true;
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
[429, 500, 502, 503, 504].forEach((statusCode) => {
|
|
105
|
+
it(`does not retry /hashtree requests on ${statusCode}`, () => {
|
|
106
|
+
const reason = new WebexHttpError.MethodNotAllowed({
|
|
107
|
+
statusCode,
|
|
108
|
+
options: {
|
|
109
|
+
headers: {trackingid: 'test', 'retry-after': 1000},
|
|
110
|
+
uri: hashTreeOptions.uri,
|
|
111
|
+
},
|
|
112
|
+
body: {error: `Fake ${statusCode}`},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const handleRetryStub = sinon.stub(
|
|
116
|
+
interceptor,
|
|
117
|
+
'handleRetryRequestLocusServiceError'
|
|
118
|
+
);
|
|
119
|
+
handleRetryStub.returns(Promise.resolve());
|
|
120
|
+
|
|
121
|
+
return interceptor.onResponseError(hashTreeOptions, reason).then(
|
|
122
|
+
() => assert.fail('Expected promise to be rejected'),
|
|
123
|
+
(err) => {
|
|
124
|
+
expect(err).to.equal(reason);
|
|
125
|
+
expect(handleRetryStub.called).to.be.false;
|
|
126
|
+
handleRetryStub.restore();
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it(`does not retry /sync requests on ${statusCode}`, () => {
|
|
132
|
+
const reason = new WebexHttpError.MethodNotAllowed({
|
|
133
|
+
statusCode,
|
|
134
|
+
options: {
|
|
135
|
+
headers: {trackingid: 'test', 'retry-after': 1000},
|
|
136
|
+
uri: syncOptions.uri,
|
|
137
|
+
},
|
|
138
|
+
body: {error: `Fake ${statusCode}`},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const handleRetryStub = sinon.stub(
|
|
142
|
+
interceptor,
|
|
143
|
+
'handleRetryRequestLocusServiceError'
|
|
144
|
+
);
|
|
73
145
|
handleRetryStub.returns(Promise.resolve());
|
|
74
146
|
|
|
75
|
-
return interceptor.onResponseError(
|
|
76
|
-
|
|
147
|
+
return interceptor.onResponseError(syncOptions, reason).then(
|
|
148
|
+
() => assert.fail('Expected promise to be rejected'),
|
|
149
|
+
(err) => {
|
|
150
|
+
expect(err).to.equal(reason);
|
|
151
|
+
expect(handleRetryStub.called).to.be.false;
|
|
152
|
+
handleRetryStub.restore();
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('still retries other locus requests on 429', () => {
|
|
159
|
+
const reason429 = new WebexHttpError.MethodNotAllowed({
|
|
160
|
+
statusCode: 429,
|
|
161
|
+
options: {
|
|
162
|
+
headers: {trackingid: 'test', 'retry-after': 1000},
|
|
163
|
+
uri: options.uri,
|
|
164
|
+
},
|
|
165
|
+
body: {error: 'Too Many Requests'},
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
interceptor.webex.request = sinon.stub().returns(Promise.resolve());
|
|
169
|
+
const handleRetryStub = sinon.stub(
|
|
170
|
+
interceptor,
|
|
171
|
+
'handleRetryRequestLocusServiceError'
|
|
172
|
+
);
|
|
173
|
+
handleRetryStub.returns(Promise.resolve());
|
|
77
174
|
|
|
175
|
+
return interceptor.onResponseError(options, reason429).then(() => {
|
|
176
|
+
expect(handleRetryStub.calledOnce).to.be.true;
|
|
177
|
+
handleRetryStub.restore();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('still retries other locus requests on 503', () => {
|
|
182
|
+
interceptor.webex.request = sinon.stub().returns(Promise.resolve());
|
|
183
|
+
const handleRetryStub = sinon.stub(
|
|
184
|
+
interceptor,
|
|
185
|
+
'handleRetryRequestLocusServiceError'
|
|
186
|
+
);
|
|
187
|
+
handleRetryStub.returns(Promise.resolve());
|
|
188
|
+
|
|
189
|
+
return interceptor.onResponseError(options, reason2).then(() => {
|
|
190
|
+
expect(handleRetryStub.calledOnce).to.be.true;
|
|
191
|
+
handleRetryStub.restore();
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('URI parsing edge cases', () => {
|
|
196
|
+
const make503Reason = (uri) =>
|
|
197
|
+
new WebexHttpError.MethodNotAllowed({
|
|
198
|
+
statusCode: 503,
|
|
199
|
+
options: {headers: {trackingid: 'test', 'retry-after': 1000}, uri},
|
|
200
|
+
body: {error: 'Service Unavailable'},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const makeOptions = (uri) => ({
|
|
204
|
+
method: 'GET',
|
|
205
|
+
headers: {trackingid: 'test', 'retry-after': 1000},
|
|
206
|
+
uri,
|
|
207
|
+
body: undefined,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
[
|
|
211
|
+
'https://locus.webex.com/locus/api/v1/loci/123/session/abc/datasets/main/hashtree?rootHash=xyz',
|
|
212
|
+
'https://locus.webex.com/locus/api/v1/loci/123/session/abc/datasets/main/sync?seq=5',
|
|
213
|
+
].forEach((uri) => {
|
|
214
|
+
it(`skips retry even with query params: ${uri.split('/').pop()}`, () => {
|
|
215
|
+
const opts = makeOptions(uri);
|
|
216
|
+
const reason = make503Reason(uri);
|
|
217
|
+
const stub = sinon
|
|
218
|
+
.stub(interceptor, 'handleRetryRequestLocusServiceError')
|
|
219
|
+
.returns(Promise.resolve());
|
|
220
|
+
|
|
221
|
+
return interceptor.onResponseError(opts, reason).then(
|
|
222
|
+
() => assert.fail('Expected promise to be rejected'),
|
|
223
|
+
(err) => {
|
|
224
|
+
expect(err).to.equal(reason);
|
|
225
|
+
expect(stub.called).to.be.false;
|
|
226
|
+
stub.restore();
|
|
227
|
+
}
|
|
228
|
+
);
|
|
78
229
|
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
[
|
|
233
|
+
'https://locus.webex.com/locus/api/v1/loci/123/hashtree-v2',
|
|
234
|
+
'https://locus.webex.com/locus/api/v1/loci/123/syncData',
|
|
235
|
+
'https://locus.webex.com/locus/api/v1/loci/123/async',
|
|
236
|
+
'https://locus.webex.com/locus/api/v1/loci/123/hashtree/metadata',
|
|
237
|
+
].forEach((uri) => {
|
|
238
|
+
it(`still retries when path only partially matches: ${uri
|
|
239
|
+
.split('/')
|
|
240
|
+
.pop()}`, () => {
|
|
241
|
+
const opts = makeOptions(uri);
|
|
242
|
+
const reason = make503Reason(uri);
|
|
243
|
+
interceptor.webex.request = sinon.stub().returns(Promise.resolve());
|
|
244
|
+
const stub = sinon
|
|
245
|
+
.stub(interceptor, 'handleRetryRequestLocusServiceError')
|
|
246
|
+
.returns(Promise.resolve());
|
|
247
|
+
|
|
248
|
+
return interceptor.onResponseError(opts, reason).then(() => {
|
|
249
|
+
expect(stub.calledOnce).to.be.true;
|
|
250
|
+
stub.restore();
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('still retries when /hashtree is on a non-locus host', () => {
|
|
256
|
+
const uri = 'https://other-service.webex.com/api/v1/hashtree';
|
|
257
|
+
const opts = makeOptions(uri);
|
|
258
|
+
const reason = make503Reason(uri);
|
|
259
|
+
|
|
260
|
+
return interceptor.onResponseError(opts, reason).then(
|
|
261
|
+
() => assert.fail('Expected promise to be rejected'),
|
|
262
|
+
(err) => {
|
|
263
|
+
expect(err).to.equal(reason);
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('still retries when URI is malformed', () => {
|
|
269
|
+
const uri = 'not-a-valid-url';
|
|
270
|
+
const opts = makeOptions(uri);
|
|
271
|
+
const reason = make503Reason(uri);
|
|
272
|
+
|
|
273
|
+
return interceptor.onResponseError(opts, reason).then(
|
|
274
|
+
() => assert.fail('Expected promise to be rejected'),
|
|
275
|
+
(err) => {
|
|
276
|
+
expect(err).to.equal(reason);
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
});
|
|
79
280
|
});
|
|
80
281
|
});
|
|
81
282
|
|
|
@@ -13,6 +13,7 @@ import MediaSharesUtils from '@webex/plugin-meetings/src/locus-info//mediaShares
|
|
|
13
13
|
import LocusDeltaParser from '@webex/plugin-meetings/src/locus-info/parser';
|
|
14
14
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
15
15
|
import * as HashTreeParserModule from '@webex/plugin-meetings/src/hashTree/hashTreeParser';
|
|
16
|
+
import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
|
|
16
17
|
|
|
17
18
|
import {
|
|
18
19
|
LOCUSINFO,
|
|
@@ -3693,49 +3694,23 @@ describe('plugin-meetings', () => {
|
|
|
3693
3694
|
assert.deepEqual(callOrder, ['updateLocusUrl', 'updateMeetingInfo']);
|
|
3694
3695
|
});
|
|
3695
3696
|
|
|
3696
|
-
it('#updateLocusInfo ignores
|
|
3697
|
-
const newLocus = {
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
state: 'LEFT',
|
|
3701
|
-
},
|
|
3702
|
-
};
|
|
3697
|
+
it('#updateLocusInfo ignores locus when isSelfMovedOrBreakoutEnded returns true', () => {
|
|
3698
|
+
const newLocus = {self: {state: 'JOINED'}};
|
|
3699
|
+
|
|
3700
|
+
sinon.stub(MeetingsUtil, 'isSelfMovedOrBreakoutEnded').returns(true);
|
|
3703
3701
|
|
|
3704
3702
|
locusInfo.updateControls = sinon.stub();
|
|
3705
|
-
locusInfo.updateConversationUrl = sinon.stub();
|
|
3706
|
-
locusInfo.updateCreated = sinon.stub();
|
|
3707
3703
|
locusInfo.updateFullState = sinon.stub();
|
|
3708
|
-
locusInfo.updateHostInfo = sinon.stub();
|
|
3709
|
-
locusInfo.updateMeetingInfo = sinon.stub();
|
|
3710
|
-
locusInfo.updateMediaShares = sinon.stub();
|
|
3711
|
-
locusInfo.updateReplaces = sinon.stub();
|
|
3712
3704
|
locusInfo.updateSelf = sinon.stub();
|
|
3713
|
-
locusInfo.updateLocusUrl = sinon.stub();
|
|
3714
|
-
locusInfo.updateAclUrl = sinon.stub();
|
|
3715
|
-
locusInfo.updateBasequence = sinon.stub();
|
|
3716
|
-
locusInfo.updateSequence = sinon.stub();
|
|
3717
|
-
locusInfo.updateEmbeddedApps = sinon.stub();
|
|
3718
|
-
locusInfo.updateLinks = sinon.stub();
|
|
3719
|
-
locusInfo.compareAndUpdate = sinon.stub();
|
|
3720
3705
|
|
|
3721
3706
|
locusInfo.updateLocusInfo(newLocus);
|
|
3722
3707
|
|
|
3708
|
+
assert.calledOnceWithExactly(MeetingsUtil.isSelfMovedOrBreakoutEnded, newLocus);
|
|
3723
3709
|
assert.notCalled(locusInfo.updateControls);
|
|
3724
|
-
assert.notCalled(locusInfo.updateConversationUrl);
|
|
3725
|
-
assert.notCalled(locusInfo.updateCreated);
|
|
3726
3710
|
assert.notCalled(locusInfo.updateFullState);
|
|
3727
|
-
assert.notCalled(locusInfo.updateHostInfo);
|
|
3728
|
-
assert.notCalled(locusInfo.updateMeetingInfo);
|
|
3729
|
-
assert.notCalled(locusInfo.updateMediaShares);
|
|
3730
|
-
assert.notCalled(locusInfo.updateReplaces);
|
|
3731
3711
|
assert.notCalled(locusInfo.updateSelf);
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
assert.notCalled(locusInfo.updateBasequence);
|
|
3735
|
-
assert.notCalled(locusInfo.updateSequence);
|
|
3736
|
-
assert.notCalled(locusInfo.updateEmbeddedApps);
|
|
3737
|
-
assert.notCalled(locusInfo.updateLinks);
|
|
3738
|
-
assert.notCalled(locusInfo.compareAndUpdate);
|
|
3712
|
+
|
|
3713
|
+
MeetingsUtil.isSelfMovedOrBreakoutEnded.restore();
|
|
3739
3714
|
});
|
|
3740
3715
|
|
|
3741
3716
|
it('#updateLocusInfo puts the Locus DTO top level properties at the right place in LocusInfo class', () => {
|
|
@@ -3581,6 +3581,21 @@ describe('plugin-meetings', () => {
|
|
|
3581
3581
|
'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
|
|
3582
3582
|
);
|
|
3583
3583
|
});
|
|
3584
|
+
|
|
3585
|
+
it('check breakout ended with self removed, return false', () => {
|
|
3586
|
+
webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
|
|
3587
|
+
newLocus.self.state = 'LEFT';
|
|
3588
|
+
newLocus.self.reason = 'OTHER';
|
|
3589
|
+
newLocus.self.removed = true;
|
|
3590
|
+
newLocus.fullState = {state: 'INACTIVE', endMeetingReason: 'BREAKOUT_ENDED'};
|
|
3591
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
3592
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
3593
|
+
assert.equal(result, false);
|
|
3594
|
+
assert.calledWith(
|
|
3595
|
+
LoggerProxy.logger.log,
|
|
3596
|
+
'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
|
|
3597
|
+
);
|
|
3598
|
+
});
|
|
3584
3599
|
});
|
|
3585
3600
|
|
|
3586
3601
|
describe('#isNeedHandleLocusDTO', () => {
|
|
@@ -3641,6 +3656,18 @@ describe('plugin-meetings', () => {
|
|
|
3641
3656
|
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
3642
3657
|
assert.equal(result, false);
|
|
3643
3658
|
});
|
|
3659
|
+
it('breakout session with breakout ended, return false', () => {
|
|
3660
|
+
newLocus.controls.breakout = {
|
|
3661
|
+
sessionType: 'BREAKOUT',
|
|
3662
|
+
};
|
|
3663
|
+
newLocus.self.state = 'LEFT';
|
|
3664
|
+
newLocus.self.reason = 'OTHER';
|
|
3665
|
+
newLocus.self.devices = [];
|
|
3666
|
+
newLocus.fullState = {state: 'INACTIVE', endMeetingReason: 'BREAKOUT_ENDED'};
|
|
3667
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
3668
|
+
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
3669
|
+
assert.equal(result, false);
|
|
3670
|
+
});
|
|
3644
3671
|
it('moved to lobby, return true', () => {
|
|
3645
3672
|
newLocus.controls.breakout = {
|
|
3646
3673
|
sessionType: 'MAIN',
|