@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.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.js +93 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +19 -19
- package/src/index.ts +4 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
package/dist/breakouts/index.js
CHANGED
|
@@ -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.
|
|
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;
|
|
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"}
|
|
@@ -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
|
+
}
|
package/dist/webinar/index.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
37
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
41
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
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.
|
|
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.
|
|
53
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
58
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
59
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
61
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
62
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
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,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
|
+
|