@webex/plugin-meetings 3.0.0-beta.340 → 3.0.0-beta.342

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.
@@ -209,7 +209,7 @@ var Breakout = _webexCore.WebexPlugin.extend({
209
209
  sessionId: this.sessionId
210
210
  });
211
211
  },
212
- version: "3.0.0-beta.340"
212
+ version: "3.0.0-beta.342"
213
213
  });
214
214
  var _default = Breakout;
215
215
  exports.default = _default;
@@ -1041,7 +1041,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
1041
1041
  this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1042
1042
  }
1043
1043
  },
1044
- version: "3.0.0-beta.340"
1044
+ version: "3.0.0-beta.342"
1045
1045
  });
1046
1046
  var _default = Breakouts;
1047
1047
  exports.default = _default;
package/dist/index.js CHANGED
@@ -128,6 +128,7 @@ _Object$defineProperty(exports, "getDevices", {
128
128
  var _webexCore = require("@webex/webex-core");
129
129
  var _meetings = _interopRequireDefault(require("./meetings"));
130
130
  var _config = _interopRequireDefault(require("./config"));
131
+ var _interceptors = require("./interceptors");
131
132
  var _mediaHelpers = require("@webex/media-helpers");
132
133
  var _CONSTANTS = _interopRequireWildcard(require("./constants"));
133
134
  exports.CONSTANTS = _CONSTANTS;
@@ -140,7 +141,10 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
140
141
  /* eslint-env browser */
141
142
 
142
143
  (0, _webexCore.registerPlugin)('meetings', _meetings.default, {
143
- config: _config.default
144
+ config: _config.default,
145
+ interceptors: {
146
+ LocusRetryStatusInterceptor: _interceptors.LocusRetryStatusInterceptor.create
147
+ }
144
148
  });
145
149
  var _default = _meetings.default;
146
150
  exports.default = _default;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["registerPlugin","Meetings","config"],"sources":["index.ts"],"sourcesContent":["/* eslint-env browser */\nimport {registerPlugin} from '@webex/webex-core';\n\nimport Meetings from './meetings';\nimport config from './config';\n\nregisterPlugin('meetings', Meetings, {\n config,\n});\n\nexport {\n getDevices,\n LocalStream,\n LocalDisplayStream,\n LocalSystemAudioStream,\n LocalStreamEventNames,\n StreamEventNames,\n type ServerMuteReason,\n LocalMicrophoneStreamEventNames,\n LocalCameraStreamEventNames,\n LocalMicrophoneStream,\n LocalCameraStream,\n createMicrophoneStream,\n createCameraStream,\n createDisplayStream,\n createDisplayStreamWithAudio,\n FacingMode,\n DisplaySurface,\n PresetCameraConstraints,\n type VideoContentHint,\n} from '@webex/media-helpers';\n\nexport default Meetings;\n\nexport * as CONSTANTS from './constants';\nexport * as REACTIONS from './reactions/reactions';\n\nexport {RemoteMedia} from './multistream/remoteMedia';\n\nexport {default as TriggerProxy} from './common/events/trigger-proxy';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AAEA;AACA;AAMA;AAoB8B;AAAA;AAAA;AAAA;AAO9B;AAEA;AAAsE;AAAA;AAvCtE;;AAMA,IAAAA,yBAAc,EAAC,UAAU,EAAEC,iBAAQ,EAAE;EACnCC,MAAM,EAANA;AACF,CAAC,CAAC;AAAC,eAwBYD,iBAAQ;AAAA"}
1
+ {"version":3,"names":["registerPlugin","Meetings","config","interceptors","LocusRetryStatusInterceptor","create"],"sources":["index.ts"],"sourcesContent":["/* eslint-env browser */\nimport {registerPlugin} from '@webex/webex-core';\n\nimport Meetings from './meetings';\nimport config from './config';\nimport {LocusRetryStatusInterceptor} from './interceptors';\n\nregisterPlugin('meetings', Meetings, {\n config,\n interceptors: {\n LocusRetryStatusInterceptor: LocusRetryStatusInterceptor.create,\n },\n});\n\nexport {\n getDevices,\n LocalStream,\n LocalDisplayStream,\n LocalSystemAudioStream,\n LocalStreamEventNames,\n StreamEventNames,\n type ServerMuteReason,\n LocalMicrophoneStreamEventNames,\n LocalCameraStreamEventNames,\n LocalMicrophoneStream,\n LocalCameraStream,\n createMicrophoneStream,\n createCameraStream,\n createDisplayStream,\n createDisplayStreamWithAudio,\n FacingMode,\n DisplaySurface,\n PresetCameraConstraints,\n type VideoContentHint,\n} from '@webex/media-helpers';\n\nexport default Meetings;\n\nexport * as CONSTANTS from './constants';\nexport * as REACTIONS from './reactions/reactions';\n\nexport {RemoteMedia} from './multistream/remoteMedia';\n\nexport {default as TriggerProxy} from './common/events/trigger-proxy';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AAEA;AACA;AACA;AASA;AAoB8B;AAAA;AAAA;AAAA;AAO9B;AAEA;AAAsE;AAAA;AA3CtE;;AAOA,IAAAA,yBAAc,EAAC,UAAU,EAAEC,iBAAQ,EAAE;EACnCC,MAAM,EAANA,eAAM;EACNC,YAAY,EAAE;IACZC,2BAA2B,EAAEA,yCAA2B,CAACC;EAC3D;AACF,CAAC,CAAC;AAAC,eAwBYJ,iBAAQ;AAAA"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
+ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
5
+ _Object$defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ _Object$defineProperty(exports, "LocusRetryStatusInterceptor", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _locusRetry.default;
12
+ }
13
+ });
14
+ var _locusRetry = _interopRequireDefault(require("./locusRetry"));
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["import LocusRetryStatusInterceptor from './locusRetry';\n\nexport {LocusRetryStatusInterceptor};\n"],"mappings":";;;;;;;;;;;;;AAAA"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
4
+ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
5
+ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
6
+ _Object$defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.default = void 0;
10
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
11
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
12
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
13
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
14
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
15
+ var _weakMap = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/weak-map"));
16
+ var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
17
+ var _httpCore = require("@webex/http-core");
18
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
19
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
20
+ var rateLimitExpiryTime = new _weakMap.default();
21
+ /**
22
+ * @class
23
+ */
24
+ var LocusRetryStatusInterceptor = /*#__PURE__*/function (_Interceptor) {
25
+ (0, _inherits2.default)(LocusRetryStatusInterceptor, _Interceptor);
26
+ var _super = _createSuper(LocusRetryStatusInterceptor);
27
+ function LocusRetryStatusInterceptor() {
28
+ (0, _classCallCheck2.default)(this, LocusRetryStatusInterceptor);
29
+ return _super.apply(this, arguments);
30
+ }
31
+ (0, _createClass2.default)(LocusRetryStatusInterceptor, [{
32
+ key: "onResponseError",
33
+ value:
34
+ /**
35
+ * Handle response errors
36
+ * @param {Object} options
37
+ * @param {WebexHttpError} reason
38
+ * @returns {Promise<WebexHttpError>}
39
+ */
40
+ function onResponseError(options, reason) {
41
+ if ((reason.statusCode === 503 || reason.statusCode === 429) && options.uri.includes('locus')) {
42
+ var hasRetriedLocusRequest = rateLimitExpiryTime.get(this);
43
+ var retryAfterTime = options.headers['retry-after'] || 2000;
44
+ if (hasRetriedLocusRequest) {
45
+ rateLimitExpiryTime.set(this, false);
46
+ return _promise.default.reject(options);
47
+ }
48
+ rateLimitExpiryTime.set(this, true);
49
+ return this.handleRetryRequestLocusServiceError(options, retryAfterTime);
50
+ }
51
+ return _promise.default.reject(reason);
52
+ }
53
+
54
+ /**
55
+ * Handle retries for locus service unavailable errors
56
+ * @param {Object} options associated with the request
57
+ * @param {number} retryAfterTime retry after time in milliseconds
58
+ * @returns {Promise}
59
+ */
60
+ }, {
61
+ key: "handleRetryRequestLocusServiceError",
62
+ value: function handleRetryRequestLocusServiceError(options, retryAfterTime) {
63
+ var _this = this;
64
+ return new _promise.default(function (resolve, reject) {
65
+ var timeout = setTimeout(function () {
66
+ clearTimeout(timeout);
67
+
68
+ // @ts-ignore
69
+ _this.webex.request({
70
+ method: options.method,
71
+ uri: options.uri,
72
+ body: options.body
73
+ }).then(resolve).catch(reject);
74
+ }, retryAfterTime);
75
+ });
76
+ }
77
+ }], [{
78
+ key: "create",
79
+ value:
80
+ /**
81
+ * @returns {LocusRetryStatusInterceptor}
82
+ */
83
+ function create() {
84
+ // @ts-ignore
85
+ return new LocusRetryStatusInterceptor({
86
+ webex: this
87
+ });
88
+ }
89
+ }]);
90
+ return LocusRetryStatusInterceptor;
91
+ }(_httpCore.Interceptor);
92
+ exports.default = LocusRetryStatusInterceptor;
93
+ //# sourceMappingURL=locusRetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rateLimitExpiryTime","LocusRetryStatusInterceptor","options","reason","statusCode","uri","includes","hasRetriedLocusRequest","get","retryAfterTime","headers","set","reject","handleRetryRequestLocusServiceError","resolve","timeout","setTimeout","clearTimeout","webex","request","method","body","then","catch","Interceptor"],"sources":["locusRetry.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {Interceptor} from '@webex/http-core';\n\nconst rateLimitExpiryTime = new WeakMap();\n/**\n * @class\n */\nexport default class LocusRetryStatusInterceptor extends Interceptor {\n /**\n * @returns {LocusRetryStatusInterceptor}\n */\n static create() {\n // @ts-ignore\n return new LocusRetryStatusInterceptor({webex: this});\n }\n\n /**\n * Handle response errors\n * @param {Object} options\n * @param {WebexHttpError} reason\n * @returns {Promise<WebexHttpError>}\n */\n onResponseError(options, reason) {\n if ((reason.statusCode === 503 || reason.statusCode === 429) && options.uri.includes('locus')) {\n const hasRetriedLocusRequest = rateLimitExpiryTime.get(this);\n const retryAfterTime = options.headers['retry-after'] || 2000;\n\n if (hasRetriedLocusRequest) {\n rateLimitExpiryTime.set(this, false);\n\n return Promise.reject(options);\n }\n rateLimitExpiryTime.set(this, true);\n\n return this.handleRetryRequestLocusServiceError(options, retryAfterTime);\n }\n\n return Promise.reject(reason);\n }\n\n /**\n * Handle retries for locus service unavailable errors\n * @param {Object} options associated with the request\n * @param {number} retryAfterTime retry after time in milliseconds\n * @returns {Promise}\n */\n handleRetryRequestLocusServiceError(options, retryAfterTime) {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n clearTimeout(timeout);\n\n // @ts-ignore\n this.webex\n .request({\n method: options.method,\n uri: options.uri,\n body: options.body,\n })\n .then(resolve)\n .catch(reject);\n }, retryAfterTime);\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAIA;AAA6C;AAAA;AAE7C,IAAMA,mBAAmB,GAAG,sBAAa;AACzC;AACA;AACA;AAFA,IAGqBC,2BAA2B;EAAA;EAAA;EAAA;IAAA;IAAA;EAAA;EAAA;IAAA;IAAA;IAS9C;AACF;AACA;AACA;AACA;AACA;IACE,yBAAgBC,OAAO,EAAEC,MAAM,EAAE;MAC/B,IAAI,CAACA,MAAM,CAACC,UAAU,KAAK,GAAG,IAAID,MAAM,CAACC,UAAU,KAAK,GAAG,KAAKF,OAAO,CAACG,GAAG,CAACC,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC7F,IAAMC,sBAAsB,GAAGP,mBAAmB,CAACQ,GAAG,CAAC,IAAI,CAAC;QAC5D,IAAMC,cAAc,GAAGP,OAAO,CAACQ,OAAO,CAAC,aAAa,CAAC,IAAI,IAAI;QAE7D,IAAIH,sBAAsB,EAAE;UAC1BP,mBAAmB,CAACW,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;UAEpC,OAAO,iBAAQC,MAAM,CAACV,OAAO,CAAC;QAChC;QACAF,mBAAmB,CAACW,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;QAEnC,OAAO,IAAI,CAACE,mCAAmC,CAACX,OAAO,EAAEO,cAAc,CAAC;MAC1E;MAEA,OAAO,iBAAQG,MAAM,CAACT,MAAM,CAAC;IAC/B;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA,OAMA,6CAAoCD,OAAO,EAAEO,cAAc,EAAE;MAAA;MAC3D,OAAO,qBAAY,UAACK,OAAO,EAAEF,MAAM,EAAK;QACtC,IAAMG,OAAO,GAAGC,UAAU,CAAC,YAAM;UAC/BC,YAAY,CAACF,OAAO,CAAC;;UAErB;UACA,KAAI,CAACG,KAAK,CACPC,OAAO,CAAC;YACPC,MAAM,EAAElB,OAAO,CAACkB,MAAM;YACtBf,GAAG,EAAEH,OAAO,CAACG,GAAG;YAChBgB,IAAI,EAAEnB,OAAO,CAACmB;UAChB,CAAC,CAAC,CACDC,IAAI,CAACR,OAAO,CAAC,CACbS,KAAK,CAACX,MAAM,CAAC;QAClB,CAAC,EAAEH,cAAc,CAAC;MACpB,CAAC,CAAC;IACJ;EAAC;IAAA;IAAA;IAtDD;AACF;AACA;IACE,kBAAgB;MACd;MACA,OAAO,IAAIR,2BAA2B,CAAC;QAACiB,KAAK,EAAE;MAAI,CAAC,CAAC;IACvD;EAAC;EAAA;AAAA,EAPsDM,qBAAW;AAAA"}
@@ -359,7 +359,7 @@ var SimultaneousInterpretation = _webexCore.WebexPlugin.extend({
359
359
  throw error;
360
360
  });
361
361
  },
362
- version: "3.0.0-beta.340"
362
+ version: "3.0.0-beta.342"
363
363
  });
364
364
  var _default = SimultaneousInterpretation;
365
365
  exports.default = _default;
@@ -18,7 +18,7 @@ var SILanguage = _webexCore.WebexPlugin.extend({
18
18
  languageCode: 'number',
19
19
  languageName: 'string'
20
20
  },
21
- version: "3.0.0-beta.340"
21
+ version: "3.0.0-beta.342"
22
22
  });
23
23
  var _default = SILanguage;
24
24
  exports.default = _default;
@@ -0,0 +1,2 @@
1
+ import LocusRetryStatusInterceptor from './locusRetry';
2
+ export { LocusRetryStatusInterceptor };
@@ -0,0 +1,27 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+ import { Interceptor } from '@webex/http-core';
5
+ /**
6
+ * @class
7
+ */
8
+ export default class LocusRetryStatusInterceptor extends Interceptor {
9
+ /**
10
+ * @returns {LocusRetryStatusInterceptor}
11
+ */
12
+ static create(): LocusRetryStatusInterceptor;
13
+ /**
14
+ * Handle response errors
15
+ * @param {Object} options
16
+ * @param {WebexHttpError} reason
17
+ * @returns {Promise<WebexHttpError>}
18
+ */
19
+ onResponseError(options: any, reason: any): Promise<unknown>;
20
+ /**
21
+ * Handle retries for locus service unavailable errors
22
+ * @param {Object} options associated with the request
23
+ * @param {number} retryAfterTime retry after time in milliseconds
24
+ * @returns {Promise}
25
+ */
26
+ handleRetryRequestLocusServiceError(options: any, retryAfterTime: any): Promise<unknown>;
27
+ }
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
62
62
  updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
63
63
  this.set('canManageWebcast', canManageWebcast);
64
64
  },
65
- version: "3.0.0-beta.340"
65
+ version: "3.0.0-beta.342"
66
66
  });
67
67
  var _default = Webinar;
68
68
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.340",
3
+ "version": "3.0.0-beta.342",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -33,12 +33,12 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@peculiar/webcrypto": "^1.4.3",
36
- "@webex/plugin-meetings": "3.0.0-beta.340",
37
- "@webex/test-helper-chai": "3.0.0-beta.340",
38
- "@webex/test-helper-mocha": "3.0.0-beta.340",
39
- "@webex/test-helper-mock-webex": "3.0.0-beta.340",
40
- "@webex/test-helper-retry": "3.0.0-beta.340",
41
- "@webex/test-helper-test-users": "3.0.0-beta.340",
36
+ "@webex/plugin-meetings": "3.0.0-beta.342",
37
+ "@webex/test-helper-chai": "3.0.0-beta.342",
38
+ "@webex/test-helper-mocha": "3.0.0-beta.342",
39
+ "@webex/test-helper-mock-webex": "3.0.0-beta.342",
40
+ "@webex/test-helper-retry": "3.0.0-beta.342",
41
+ "@webex/test-helper-test-users": "3.0.0-beta.342",
42
42
  "chai": "^4.3.4",
43
43
  "chai-as-promised": "^7.1.1",
44
44
  "jsdom-global": "3.0.2",
@@ -47,19 +47,19 @@
47
47
  "typescript": "^4.7.4"
48
48
  },
49
49
  "dependencies": {
50
- "@webex/common": "3.0.0-beta.340",
50
+ "@webex/common": "3.0.0-beta.342",
51
51
  "@webex/internal-media-core": "2.2.4",
52
- "@webex/internal-plugin-conversation": "3.0.0-beta.340",
53
- "@webex/internal-plugin-device": "3.0.0-beta.340",
54
- "@webex/internal-plugin-llm": "3.0.0-beta.340",
55
- "@webex/internal-plugin-mercury": "3.0.0-beta.340",
56
- "@webex/internal-plugin-metrics": "3.0.0-beta.340",
57
- "@webex/internal-plugin-support": "3.0.0-beta.340",
58
- "@webex/internal-plugin-user": "3.0.0-beta.340",
59
- "@webex/media-helpers": "3.0.0-beta.340",
60
- "@webex/plugin-people": "3.0.0-beta.340",
61
- "@webex/plugin-rooms": "3.0.0-beta.340",
62
- "@webex/webex-core": "3.0.0-beta.340",
52
+ "@webex/internal-plugin-conversation": "3.0.0-beta.342",
53
+ "@webex/internal-plugin-device": "3.0.0-beta.342",
54
+ "@webex/internal-plugin-llm": "3.0.0-beta.342",
55
+ "@webex/internal-plugin-mercury": "3.0.0-beta.342",
56
+ "@webex/internal-plugin-metrics": "3.0.0-beta.342",
57
+ "@webex/internal-plugin-support": "3.0.0-beta.342",
58
+ "@webex/internal-plugin-user": "3.0.0-beta.342",
59
+ "@webex/media-helpers": "3.0.0-beta.342",
60
+ "@webex/plugin-people": "3.0.0-beta.342",
61
+ "@webex/plugin-rooms": "3.0.0-beta.342",
62
+ "@webex/webex-core": "3.0.0-beta.342",
63
63
  "ampersand-collection": "^2.0.2",
64
64
  "bowser": "^2.11.0",
65
65
  "btoa": "^1.2.1",
package/src/index.ts CHANGED
@@ -3,9 +3,13 @@ import {registerPlugin} from '@webex/webex-core';
3
3
 
4
4
  import Meetings from './meetings';
5
5
  import config from './config';
6
+ import {LocusRetryStatusInterceptor} from './interceptors';
6
7
 
7
8
  registerPlugin('meetings', Meetings, {
8
9
  config,
10
+ interceptors: {
11
+ LocusRetryStatusInterceptor: LocusRetryStatusInterceptor.create,
12
+ },
9
13
  });
10
14
 
11
15
  export {
@@ -0,0 +1,3 @@
1
+ import LocusRetryStatusInterceptor from './locusRetry';
2
+
3
+ export {LocusRetryStatusInterceptor};
@@ -0,0 +1,67 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {Interceptor} from '@webex/http-core';
6
+
7
+ const rateLimitExpiryTime = new WeakMap();
8
+ /**
9
+ * @class
10
+ */
11
+ export default class LocusRetryStatusInterceptor extends Interceptor {
12
+ /**
13
+ * @returns {LocusRetryStatusInterceptor}
14
+ */
15
+ static create() {
16
+ // @ts-ignore
17
+ return new LocusRetryStatusInterceptor({webex: this});
18
+ }
19
+
20
+ /**
21
+ * Handle response errors
22
+ * @param {Object} options
23
+ * @param {WebexHttpError} reason
24
+ * @returns {Promise<WebexHttpError>}
25
+ */
26
+ onResponseError(options, reason) {
27
+ if ((reason.statusCode === 503 || reason.statusCode === 429) && options.uri.includes('locus')) {
28
+ const hasRetriedLocusRequest = rateLimitExpiryTime.get(this);
29
+ const retryAfterTime = options.headers['retry-after'] || 2000;
30
+
31
+ if (hasRetriedLocusRequest) {
32
+ rateLimitExpiryTime.set(this, false);
33
+
34
+ return Promise.reject(options);
35
+ }
36
+ rateLimitExpiryTime.set(this, true);
37
+
38
+ return this.handleRetryRequestLocusServiceError(options, retryAfterTime);
39
+ }
40
+
41
+ return Promise.reject(reason);
42
+ }
43
+
44
+ /**
45
+ * Handle retries for locus service unavailable errors
46
+ * @param {Object} options associated with the request
47
+ * @param {number} retryAfterTime retry after time in milliseconds
48
+ * @returns {Promise}
49
+ */
50
+ handleRetryRequestLocusServiceError(options, retryAfterTime) {
51
+ return new Promise((resolve, reject) => {
52
+ const timeout = setTimeout(() => {
53
+ clearTimeout(timeout);
54
+
55
+ // @ts-ignore
56
+ this.webex
57
+ .request({
58
+ method: options.method,
59
+ uri: options.uri,
60
+ body: options.body,
61
+ })
62
+ .then(resolve)
63
+ .catch(reject);
64
+ }, retryAfterTime);
65
+ });
66
+ }
67
+ }
@@ -0,0 +1,131 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ /* eslint-disable camelcase */
6
+ import {assert} from '@webex/test-helper-chai';
7
+ import { expect } from "@webex/test-helper-chai";
8
+ import MockWebex from '@webex/test-helper-mock-webex';
9
+ import {LocusRetryStatusInterceptor} from "@webex/plugin-meetings/src/interceptors";
10
+ import {WebexHttpError} from '@webex/webex-core';
11
+ import Meetings from '@webex/plugin-meetings';
12
+ import sinon from 'sinon';
13
+
14
+ describe('plugin-meetings', () => {
15
+ describe('Interceptors', () => {
16
+ describe('LocusRetryStatusInterceptor', () => {
17
+ let interceptor, webex;
18
+ beforeEach(() => {
19
+ webex = new MockWebex({
20
+ children: {
21
+ meeting: Meetings,
22
+ },
23
+ });
24
+ interceptor = Reflect.apply(LocusRetryStatusInterceptor.create, {
25
+ sessionId: 'mock-webex_uuid',
26
+ }, []);
27
+ });
28
+ describe('#onResponseError', () => {
29
+ const options = {
30
+ method: 'POST',
31
+ headers: {
32
+ trackingid: 'test',
33
+ 'retry-after': 1000,
34
+ },
35
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
36
+ body: 'foo'
37
+ };
38
+ const reason1 = new WebexHttpError.MethodNotAllowed({
39
+ statusCode: 403,
40
+ options: {
41
+ headers: {
42
+ trackingid: 'test',
43
+ 'retry-after': 1000,
44
+ },
45
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
46
+ },
47
+ body: {
48
+ error: 'POST not allwed',
49
+ },
50
+ });
51
+ const reason2 = new WebexHttpError.MethodNotAllowed({
52
+ statusCode: 503,
53
+ options: {
54
+ headers: {
55
+ trackingid: 'test',
56
+ 'retry-after': 1000,
57
+ },
58
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
59
+ },
60
+ body: {
61
+ error: 'Service Unavailable',
62
+ },
63
+ });
64
+
65
+ it('rejects when not locus service unavailable error', () => {
66
+ return assert.isRejected(interceptor.onResponseError(options, reason1));
67
+ });
68
+
69
+ it('calls handleRetryRequestLocusServiceError with correct retry time when locus service unavailable error', () => {
70
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve());
71
+ const handleRetryStub = sinon.stub(interceptor, 'handleRetryRequestLocusServiceError');
72
+ handleRetryStub.returns(Promise.resolve());
73
+
74
+ return interceptor.onResponseError(options, reason2).then(() => {
75
+ expect(handleRetryStub.calledWith(options, 1000)).to.be.true;
76
+
77
+ });
78
+ });
79
+ });
80
+
81
+ describe('#handleRetryRequestLocusServiceError', () => {
82
+ const options = {
83
+ method: 'POST',
84
+ headers: {
85
+ trackingid: 'test',
86
+ },
87
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
88
+ body: 'foo'
89
+ };
90
+ const retryAfterTime = 2000;
91
+
92
+ it('returns the correct resolved value when the request is successful', () => {
93
+ const mockResponse = 'mock response'
94
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
95
+
96
+ return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
97
+ .then((response) => {
98
+ expect(response).to.equal(mockResponse);
99
+ });
100
+ });
101
+
102
+ it('rejects the promise when the request is unsuccessful', () => {
103
+ const rejectionReason = 'Service Unavaialble after retry';
104
+
105
+ interceptor.webex.request = sinon.stub().returns(Promise.reject(rejectionReason));
106
+
107
+ return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
108
+ .catch((error) => {
109
+ expect(error).to.equal(rejectionReason);
110
+ });
111
+ });
112
+
113
+ it('retries the request after the specified time', () => {
114
+ let clock;
115
+ clock = sinon.useFakeTimers();
116
+ const mockResponse = 'mock response'
117
+
118
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
119
+ const promise = interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime);
120
+
121
+ clock.tick(retryAfterTime);
122
+
123
+ return promise.then(() => {
124
+ expect(interceptor.webex.request.calledOnce).to.be.true;
125
+ });
126
+ });
127
+ });
128
+ });
129
+ });
130
+ });
131
+