rx-player 3.29.0-dev.2022091600 → 3.29.0-dev.2022103100
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/CHANGELOG.md +22 -10
- package/MAINTAINERS.md +2 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +4 -1
- package/dist/_esm5.processed/compat/browser_detection.js +7 -1
- package/dist/_esm5.processed/compat/can_reuse_media_keys.d.ts +12 -0
- package/dist/_esm5.processed/compat/can_reuse_media_keys.js +15 -0
- package/dist/_esm5.processed/compat/enable_audio_track.d.ts +11 -0
- package/dist/_esm5.processed/compat/enable_audio_track.js +26 -0
- package/dist/_esm5.processed/compat/index.d.ts +4 -2
- package/dist/_esm5.processed/compat/index.js +4 -2
- package/dist/_esm5.processed/compat/{should_renew_media_keys.d.ts → should_renew_media_key_system_access.d.ts} +3 -3
- package/dist/_esm5.processed/compat/{should_renew_media_keys.js → should_renew_media_key_system_access.js} +3 -3
- package/dist/_esm5.processed/config.d.ts +1 -0
- package/dist/_esm5.processed/core/api/playback_observer.d.ts +14 -5
- package/dist/_esm5.processed/core/api/playback_observer.js +54 -22
- package/dist/_esm5.processed/core/api/public_api.d.ts +7 -4
- package/dist/_esm5.processed/core/api/public_api.js +79 -61
- package/dist/_esm5.processed/core/api/tracks_management/media_element_track_choice_manager.js +9 -10
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +1 -1
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +3 -3
- package/dist/_esm5.processed/core/decrypt/get_media_keys.js +4 -1
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +98 -0
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +173 -0
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +4 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +2 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +15 -16
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +3 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.js +5 -2
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.d.ts +103 -0
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +414 -0
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.d.ts +4 -3
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +21 -22
- package/dist/_esm5.processed/core/init/initialize_media_source.d.ts +18 -4
- package/dist/_esm5.processed/core/init/initialize_media_source.js +10 -2
- package/dist/_esm5.processed/core/init/load_on_media_source.js +7 -1
- package/dist/_esm5.processed/core/init/stall_avoider.js +3 -1
- package/dist/_esm5.processed/default_config.d.ts +11 -0
- package/dist/_esm5.processed/default_config.js +11 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +1 -1
- package/dist/_esm5.processed/manifest/manifest.js +11 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +12 -1
- package/dist/_esm5.processed/manifest/representation.js +1 -0
- package/dist/_esm5.processed/manifest/representation_index/static.d.ts +1 -1
- package/dist/_esm5.processed/manifest/representation_index/static.js +2 -2
- package/dist/_esm5.processed/manifest/representation_index/types.d.ts +32 -15
- package/dist/_esm5.processed/manifest/update_period_in_place.js +1 -0
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.d.ts +10 -9
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.js +11 -11
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_init_segment.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_init_segment.js +3 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.d.ts +7 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.js +12 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.d.ts +5 -6
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.js +16 -16
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +11 -10
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +14 -13
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.d.ts +3 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.js +4 -12
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_mpd.js +2 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representation_index.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +6 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.d.ts +1 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.js +3 -8
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/BaseURL.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/BaseURL.js +2 -20
- package/dist/_esm5.processed/parsers/manifest/dash/node_parser_types.d.ts +0 -6
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.js +0 -11
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/types.d.ts +5 -1
- package/dist/_esm5.processed/parsers/manifest/local/parse_local_manifest.js +2 -1
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/metaplaylist_parser.js +7 -1
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +17 -11
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/types.d.ts +24 -0
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_extent.js +8 -1
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_origin.js +9 -1
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/create_element.js +2 -1
- package/dist/_esm5.processed/transports/dash/construct_segment_url.d.ts +18 -0
- package/dist/_esm5.processed/transports/dash/construct_segment_url.js +21 -0
- package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/image_pipelines.js +5 -3
- package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -2
- package/dist/_esm5.processed/transports/dash/text_loader.js +4 -2
- package/dist/_esm5.processed/transports/dash/text_parser.js +3 -1
- package/dist/_esm5.processed/transports/local/segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/local/segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +8 -8
- package/dist/_esm5.processed/transports/smooth/pipelines.js +11 -7
- package/dist/_esm5.processed/transports/smooth/utils.d.ts +4 -2
- package/dist/_esm5.processed/transports/smooth/utils.js +7 -1
- package/dist/_esm5.processed/transports/types.d.ts +5 -3
- package/dist/_esm5.processed/utils/event_emitter.d.ts +1 -2
- package/dist/_esm5.processed/utils/resolve_url.d.ts +7 -4
- package/dist/_esm5.processed/utils/resolve_url.js +11 -8
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +5656 -13236
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +28 -23
- package/package.json +29 -29
- package/sonar-project.properties +1 -1
- package/src/compat/__tests__/can_reuse_media_keys.test.ts +54 -0
- package/src/compat/__tests__/enable_audio_track.test.ts +341 -0
- package/src/compat/__tests__/{should_renew_media_keys.test.ts → should_renew_media_key_system_access.test.ts} +7 -5
- package/src/compat/browser_detection.ts +10 -0
- package/src/compat/can_reuse_media_keys.ts +19 -0
- package/src/compat/enable_audio_track.ts +33 -0
- package/src/compat/index.ts +6 -2
- package/src/compat/{should_renew_media_keys.ts → should_renew_media_key_system_access.ts} +3 -3
- package/src/core/api/playback_observer.ts +97 -33
- package/src/core/api/public_api.ts +126 -74
- package/src/core/api/tracks_management/media_element_track_choice_manager.ts +3 -11
- package/src/core/decrypt/__tests__/__global__/media_keys.test.ts +182 -0
- package/src/core/decrypt/__tests__/__global__/utils.ts +2 -0
- package/src/core/decrypt/find_key_system.ts +3 -3
- package/src/core/decrypt/get_media_keys.ts +5 -1
- package/src/core/fetchers/cdn_prioritizer.ts +198 -0
- package/src/core/fetchers/manifest/manifest_fetcher.ts +7 -11
- package/src/core/fetchers/segment/segment_fetcher.ts +12 -10
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +10 -1
- package/src/core/fetchers/utils/schedule_request.ts +482 -0
- package/src/core/init/content_time_boundaries_observer.ts +12 -12
- package/src/core/init/initialize_media_source.ts +31 -4
- package/src/core/init/load_on_media_source.ts +11 -2
- package/src/core/init/stall_avoider.ts +4 -1
- package/src/core/stream/orchestrator/stream_orchestrator.ts +0 -1
- package/src/default_config.ts +12 -0
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +1 -0
- package/src/manifest/manifest.ts +11 -2
- package/src/manifest/representation.ts +15 -0
- package/src/manifest/representation_index/__tests__/static.test.ts +1 -1
- package/src/manifest/representation_index/static.ts +3 -3
- package/src/manifest/representation_index/types.ts +33 -15
- package/src/manifest/update_period_in_place.ts +1 -0
- package/src/parsers/manifest/dash/common/indexes/base.ts +22 -23
- package/src/parsers/manifest/dash/common/indexes/get_init_segment.ts +6 -4
- package/src/parsers/manifest/dash/common/indexes/get_segments_from_timeline.ts +5 -5
- package/src/parsers/manifest/dash/common/indexes/list.ts +19 -20
- package/src/parsers/manifest/dash/common/indexes/template.ts +23 -27
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +25 -23
- package/src/parsers/manifest/dash/common/indexes/tokens.ts +7 -18
- package/src/parsers/manifest/dash/common/parse_mpd.ts +2 -4
- package/src/parsers/manifest/dash/common/parse_representation_index.ts +1 -6
- package/src/parsers/manifest/dash/common/parse_representations.ts +9 -0
- package/src/parsers/manifest/dash/common/resolve_base_urls.ts +5 -9
- package/src/parsers/manifest/dash/js-parser/node_parsers/BaseURL.ts +2 -29
- package/src/parsers/manifest/dash/js-parser/node_parsers/__tests__/AdaptationSet.test.ts +7 -11
- package/src/parsers/manifest/dash/node_parser_types.ts +0 -7
- package/src/parsers/manifest/dash/wasm-parser/rs/events.rs +3 -1
- package/src/parsers/manifest/dash/wasm-parser/rs/processor/attributes.rs +1 -8
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.ts +0 -13
- package/src/parsers/manifest/dash/wasm-parser/ts/types.ts +8 -0
- package/src/parsers/manifest/local/parse_local_manifest.ts +1 -0
- package/src/parsers/manifest/local/representation_index.ts +2 -2
- package/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts +7 -1
- package/src/parsers/manifest/smooth/create_parser.ts +17 -13
- package/src/parsers/manifest/smooth/representation_index.ts +2 -2
- package/src/parsers/manifest/types.ts +26 -1
- package/src/parsers/manifest/utils/__tests__/get_first_time_from_adaptations.test.ts +15 -0
- package/src/parsers/manifest/utils/__tests__/get_last_time_from_adaptation.test.ts +15 -0
- package/src/parsers/texttracks/ttml/html/apply_extent.ts +8 -1
- package/src/parsers/texttracks/ttml/html/apply_origin.ts +9 -1
- package/src/parsers/texttracks/ttml/html/create_element.ts +2 -2
- package/src/transports/dash/construct_segment_url.ts +28 -0
- package/src/transports/dash/image_pipelines.ts +5 -2
- package/src/transports/dash/segment_loader.ts +5 -2
- package/src/transports/dash/text_loader.ts +5 -2
- package/src/transports/dash/text_parser.ts +3 -1
- package/src/transports/local/segment_loader.ts +3 -2
- package/src/transports/metaplaylist/pipelines.ts +28 -9
- package/src/transports/smooth/pipelines.ts +12 -6
- package/src/transports/smooth/utils.ts +13 -1
- package/src/transports/types.ts +6 -3
- package/src/utils/__tests__/event_emitter.test.ts +72 -67
- package/src/utils/__tests__/initialization_segment_cache.test.ts +7 -7
- package/src/utils/__tests__/resolve_url.test.ts +27 -23
- package/src/utils/event_emitter.ts +1 -3
- package/src/utils/resolve_url.ts +11 -8
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.d.ts +0 -85
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +0 -264
- package/dummy +0 -1
- package/src/core/fetchers/utils/try_urls_with_backoff.ts +0 -287
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2015 CANAL+ Group
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { CancellationSignal } from "../../../utils/task_canceller";
|
|
17
|
-
/** Settings to give to the backoff functions to configure their behavior. */
|
|
18
|
-
export interface IBackoffSettings {
|
|
19
|
-
/**
|
|
20
|
-
* Initial delay to wait if a request fails before making a new request, in
|
|
21
|
-
* milliseconds.
|
|
22
|
-
*/
|
|
23
|
-
baseDelay: number;
|
|
24
|
-
/**
|
|
25
|
-
* Maximum delay to wait if a request fails before making a new request, in
|
|
26
|
-
* milliseconds.
|
|
27
|
-
*/
|
|
28
|
-
maxDelay: number;
|
|
29
|
-
/**
|
|
30
|
-
* Maximum number of retries to perform on "regular" errors (e.g. due to HTTP
|
|
31
|
-
* status, integrity errors, timeouts...).
|
|
32
|
-
*/
|
|
33
|
-
maxRetryRegular: number;
|
|
34
|
-
/**
|
|
35
|
-
* Maximum number of retries to perform when it appears that the user is
|
|
36
|
-
* currently offline.
|
|
37
|
-
*/
|
|
38
|
-
maxRetryOffline: number;
|
|
39
|
-
/** Callback called when a request is retried. */
|
|
40
|
-
onRetry: (err: unknown) => void;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Specific algorithm used to perform segment and manifest requests.
|
|
44
|
-
*
|
|
45
|
-
* Here how it works:
|
|
46
|
-
*
|
|
47
|
-
* 1. You give it one or multiple URLs available for the resource you want to
|
|
48
|
-
* request (from the most important URL to the least important), the
|
|
49
|
-
* request callback itself, and some options.
|
|
50
|
-
*
|
|
51
|
-
* 2. it tries to call the request callback with the first URL:
|
|
52
|
-
* - if it works as expected, it resolves the returned Promise with that
|
|
53
|
-
* request's response.
|
|
54
|
-
* - if it fails, it calls ther `onRetry` callback given with the
|
|
55
|
-
* corresponding error and try with the next URL.
|
|
56
|
-
*
|
|
57
|
-
* 3. When all URLs have been tested (and failed), it decides - according to
|
|
58
|
-
* the error counters, configuration and errors received - if it can retry
|
|
59
|
-
* at least one of them, in the same order:
|
|
60
|
-
* - If it can, it increments the corresponding error counter, wait a
|
|
61
|
-
* delay (based on an exponential backoff) and restart the same logic
|
|
62
|
-
* for all retry-able URL.
|
|
63
|
-
* - If it can't it just reject the error through the returned Promise.
|
|
64
|
-
*
|
|
65
|
-
* Note that there are in fact two separate counters:
|
|
66
|
-
* - one for "offline" errors
|
|
67
|
-
* - one for other xhr errors
|
|
68
|
-
* Both counters are resetted if the error type changes from an error to the
|
|
69
|
-
* next.
|
|
70
|
-
*
|
|
71
|
-
* @param {Array.<string>} urls
|
|
72
|
-
* @param {Function} performRequest
|
|
73
|
-
* @param {Object} options - Configuration options.
|
|
74
|
-
* @param {Object} cancellationSignal
|
|
75
|
-
* @returns {Promise}
|
|
76
|
-
*/
|
|
77
|
-
export declare function tryURLsWithBackoff<T>(urls: Array<string | null>, performRequest: (url: string | null, cancellationSignal: CancellationSignal) => Promise<T>, options: IBackoffSettings, cancellationSignal: CancellationSignal): Promise<T>;
|
|
78
|
-
/**
|
|
79
|
-
* Lightweight version of the request algorithm, this time with only a simple
|
|
80
|
-
* Promise given.
|
|
81
|
-
* @param {Function} performRequest
|
|
82
|
-
* @param {Object} options
|
|
83
|
-
* @returns {Promise}
|
|
84
|
-
*/
|
|
85
|
-
export declare function tryRequestPromiseWithBackoff<T>(performRequest: () => Promise<T>, options: IBackoffSettings, cancellationSignal: CancellationSignal): Promise<T>;
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2015 CANAL+ Group
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
17
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
26
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
27
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
28
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
29
|
-
function step(op) {
|
|
30
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
31
|
-
while (_) try {
|
|
32
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
33
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
34
|
-
switch (op[0]) {
|
|
35
|
-
case 0: case 1: t = op; break;
|
|
36
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
37
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
38
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
39
|
-
default:
|
|
40
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
41
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
42
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
43
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
44
|
-
if (t[2]) _.ops.pop();
|
|
45
|
-
_.trys.pop(); continue;
|
|
46
|
-
}
|
|
47
|
-
op = body.call(thisArg, _);
|
|
48
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
import { isOffline } from "../../../compat";
|
|
53
|
-
import { CustomLoaderError, isKnownError, NetworkErrorTypes, RequestError, } from "../../../errors";
|
|
54
|
-
import log from "../../../log";
|
|
55
|
-
import cancellableSleep from "../../../utils/cancellable_sleep";
|
|
56
|
-
import getFuzzedDelay from "../../../utils/get_fuzzed_delay";
|
|
57
|
-
import TaskCanceller from "../../../utils/task_canceller";
|
|
58
|
-
/**
|
|
59
|
-
* Called on a loader error.
|
|
60
|
-
* Returns whether the loader request should be retried.
|
|
61
|
-
*
|
|
62
|
-
* TODO the notion of retrying or not could be transport-specific (e.g. 412 are
|
|
63
|
-
* mainly used for Smooth contents) and thus as part of the transport code (e.g.
|
|
64
|
-
* by rejecting with an error always having a `canRetry` property?).
|
|
65
|
-
* Or not, to ponder.
|
|
66
|
-
*
|
|
67
|
-
* @param {Error} error
|
|
68
|
-
* @returns {Boolean} - If true, the request can be retried.
|
|
69
|
-
*/
|
|
70
|
-
function shouldRetry(error) {
|
|
71
|
-
if (error instanceof RequestError) {
|
|
72
|
-
if (error.type === NetworkErrorTypes.ERROR_HTTP_CODE) {
|
|
73
|
-
return error.status >= 500 ||
|
|
74
|
-
error.status === 404 ||
|
|
75
|
-
error.status === 415 || // some CDN seems to use that code when
|
|
76
|
-
// requesting low-latency segments too much
|
|
77
|
-
// in advance
|
|
78
|
-
error.status === 412;
|
|
79
|
-
}
|
|
80
|
-
return error.type === NetworkErrorTypes.TIMEOUT ||
|
|
81
|
-
error.type === NetworkErrorTypes.ERROR_EVENT;
|
|
82
|
-
}
|
|
83
|
-
else if (error instanceof CustomLoaderError) {
|
|
84
|
-
if (typeof error.canRetry === "boolean") {
|
|
85
|
-
return error.canRetry;
|
|
86
|
-
}
|
|
87
|
-
if (error.xhr !== undefined) {
|
|
88
|
-
return error.xhr.status >= 500 ||
|
|
89
|
-
error.xhr.status === 404 ||
|
|
90
|
-
error.xhr.status === 415 || // some CDN seems to use that code when
|
|
91
|
-
// requesting low-latency segments too much
|
|
92
|
-
// in advance
|
|
93
|
-
error.xhr.status === 412;
|
|
94
|
-
}
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
return isKnownError(error) && error.code === "INTEGRITY_ERROR";
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Returns true if we're pretty sure that the current error is due to the
|
|
101
|
-
* user being offline.
|
|
102
|
-
* @param {Error} error
|
|
103
|
-
* @returns {Boolean}
|
|
104
|
-
*/
|
|
105
|
-
function isOfflineRequestError(error) {
|
|
106
|
-
if (error instanceof RequestError) {
|
|
107
|
-
return error.type === NetworkErrorTypes.ERROR_EVENT &&
|
|
108
|
-
isOffline();
|
|
109
|
-
}
|
|
110
|
-
else if (error instanceof CustomLoaderError) {
|
|
111
|
-
return error.isOfflineError;
|
|
112
|
-
}
|
|
113
|
-
return false; // under doubt, return false
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Guess the type of error obtained.
|
|
117
|
-
* @param {*} error
|
|
118
|
-
* @returns {number}
|
|
119
|
-
*/
|
|
120
|
-
function getRequestErrorType(error) {
|
|
121
|
-
return isOfflineRequestError(error) ? 2 /* REQUEST_ERROR_TYPES.Offline */ :
|
|
122
|
-
1 /* REQUEST_ERROR_TYPES.Regular */;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Specific algorithm used to perform segment and manifest requests.
|
|
126
|
-
*
|
|
127
|
-
* Here how it works:
|
|
128
|
-
*
|
|
129
|
-
* 1. You give it one or multiple URLs available for the resource you want to
|
|
130
|
-
* request (from the most important URL to the least important), the
|
|
131
|
-
* request callback itself, and some options.
|
|
132
|
-
*
|
|
133
|
-
* 2. it tries to call the request callback with the first URL:
|
|
134
|
-
* - if it works as expected, it resolves the returned Promise with that
|
|
135
|
-
* request's response.
|
|
136
|
-
* - if it fails, it calls ther `onRetry` callback given with the
|
|
137
|
-
* corresponding error and try with the next URL.
|
|
138
|
-
*
|
|
139
|
-
* 3. When all URLs have been tested (and failed), it decides - according to
|
|
140
|
-
* the error counters, configuration and errors received - if it can retry
|
|
141
|
-
* at least one of them, in the same order:
|
|
142
|
-
* - If it can, it increments the corresponding error counter, wait a
|
|
143
|
-
* delay (based on an exponential backoff) and restart the same logic
|
|
144
|
-
* for all retry-able URL.
|
|
145
|
-
* - If it can't it just reject the error through the returned Promise.
|
|
146
|
-
*
|
|
147
|
-
* Note that there are in fact two separate counters:
|
|
148
|
-
* - one for "offline" errors
|
|
149
|
-
* - one for other xhr errors
|
|
150
|
-
* Both counters are resetted if the error type changes from an error to the
|
|
151
|
-
* next.
|
|
152
|
-
*
|
|
153
|
-
* @param {Array.<string>} urls
|
|
154
|
-
* @param {Function} performRequest
|
|
155
|
-
* @param {Object} options - Configuration options.
|
|
156
|
-
* @param {Object} cancellationSignal
|
|
157
|
-
* @returns {Promise}
|
|
158
|
-
*/
|
|
159
|
-
export function tryURLsWithBackoff(urls, performRequest, options, cancellationSignal) {
|
|
160
|
-
if (cancellationSignal.isCancelled) {
|
|
161
|
-
return Promise.reject(cancellationSignal.cancellationError);
|
|
162
|
-
}
|
|
163
|
-
var baseDelay = options.baseDelay, maxDelay = options.maxDelay, maxRetryRegular = options.maxRetryRegular, maxRetryOffline = options.maxRetryOffline, onRetry = options.onRetry;
|
|
164
|
-
var retryCount = 0;
|
|
165
|
-
var lastError = 0 /* REQUEST_ERROR_TYPES.None */;
|
|
166
|
-
var urlsToTry = urls.slice();
|
|
167
|
-
if (urlsToTry.length === 0) {
|
|
168
|
-
log.warn("Fetchers: no URL given to `tryURLsWithBackoff`.");
|
|
169
|
-
return Promise.reject(new Error("No URL to request"));
|
|
170
|
-
}
|
|
171
|
-
return tryURLsRecursively(urlsToTry[0], 0);
|
|
172
|
-
/**
|
|
173
|
-
* Try to do the request of a given `url` which corresponds to the `index`
|
|
174
|
-
* argument in the `urlsToTry` Array.
|
|
175
|
-
*
|
|
176
|
-
* If it fails try the next one.
|
|
177
|
-
*
|
|
178
|
-
* If all URLs fail, start a timer and retry the first element in that array
|
|
179
|
-
* by following the configuration.
|
|
180
|
-
*
|
|
181
|
-
* @param {string|null} url
|
|
182
|
-
* @param {number} index
|
|
183
|
-
* @returns {Promise}
|
|
184
|
-
*/
|
|
185
|
-
function tryURLsRecursively(url, index) {
|
|
186
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
187
|
-
var res, error_1, newIndex, currentError, maxRetry, newIndex, delay, fuzzedDelay, nextURL;
|
|
188
|
-
return __generator(this, function (_a) {
|
|
189
|
-
switch (_a.label) {
|
|
190
|
-
case 0:
|
|
191
|
-
_a.trys.push([0, 2, , 4]);
|
|
192
|
-
return [4 /*yield*/, performRequest(url, cancellationSignal)];
|
|
193
|
-
case 1:
|
|
194
|
-
res = _a.sent();
|
|
195
|
-
return [2 /*return*/, res];
|
|
196
|
-
case 2:
|
|
197
|
-
error_1 = _a.sent();
|
|
198
|
-
if (TaskCanceller.isCancellationError(error_1)) {
|
|
199
|
-
throw error_1;
|
|
200
|
-
}
|
|
201
|
-
if (!shouldRetry(error_1)) {
|
|
202
|
-
// ban this URL
|
|
203
|
-
if (urlsToTry.length <= 1) { // This was the last one, throw
|
|
204
|
-
throw error_1;
|
|
205
|
-
}
|
|
206
|
-
// else, remove that element from the array and go the next URL
|
|
207
|
-
urlsToTry.splice(index, 1);
|
|
208
|
-
newIndex = index >= urlsToTry.length - 1 ? 0 :
|
|
209
|
-
index;
|
|
210
|
-
onRetry(error_1);
|
|
211
|
-
if (cancellationSignal.isCancelled) {
|
|
212
|
-
throw cancellationSignal.cancellationError;
|
|
213
|
-
}
|
|
214
|
-
return [2 /*return*/, tryURLsRecursively(urlsToTry[newIndex], newIndex)];
|
|
215
|
-
}
|
|
216
|
-
currentError = getRequestErrorType(error_1);
|
|
217
|
-
maxRetry = currentError === 2 /* REQUEST_ERROR_TYPES.Offline */ ? maxRetryOffline :
|
|
218
|
-
maxRetryRegular;
|
|
219
|
-
if (currentError !== lastError) {
|
|
220
|
-
retryCount = 0;
|
|
221
|
-
lastError = currentError;
|
|
222
|
-
}
|
|
223
|
-
if (index < urlsToTry.length - 1) { // there is still URLs to test
|
|
224
|
-
newIndex = index + 1;
|
|
225
|
-
onRetry(error_1);
|
|
226
|
-
if (cancellationSignal.isCancelled) {
|
|
227
|
-
throw cancellationSignal.cancellationError;
|
|
228
|
-
}
|
|
229
|
-
return [2 /*return*/, tryURLsRecursively(urlsToTry[newIndex], newIndex)];
|
|
230
|
-
}
|
|
231
|
-
// Here, we were using the last element of the `urlsToTry` array.
|
|
232
|
-
// Increment counter and restart with the first URL
|
|
233
|
-
retryCount++;
|
|
234
|
-
if (retryCount > maxRetry) {
|
|
235
|
-
throw error_1;
|
|
236
|
-
}
|
|
237
|
-
delay = Math.min(baseDelay * Math.pow(2, retryCount - 1), maxDelay);
|
|
238
|
-
fuzzedDelay = getFuzzedDelay(delay);
|
|
239
|
-
nextURL = urlsToTry[0];
|
|
240
|
-
onRetry(error_1);
|
|
241
|
-
if (cancellationSignal.isCancelled) {
|
|
242
|
-
throw cancellationSignal.cancellationError;
|
|
243
|
-
}
|
|
244
|
-
return [4 /*yield*/, cancellableSleep(fuzzedDelay, cancellationSignal)];
|
|
245
|
-
case 3:
|
|
246
|
-
_a.sent();
|
|
247
|
-
return [2 /*return*/, tryURLsRecursively(nextURL, 0)];
|
|
248
|
-
case 4: return [2 /*return*/];
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Lightweight version of the request algorithm, this time with only a simple
|
|
256
|
-
* Promise given.
|
|
257
|
-
* @param {Function} performRequest
|
|
258
|
-
* @param {Object} options
|
|
259
|
-
* @returns {Promise}
|
|
260
|
-
*/
|
|
261
|
-
export function tryRequestPromiseWithBackoff(performRequest, options, cancellationSignal) {
|
|
262
|
-
// same than for a single unknown URL
|
|
263
|
-
return tryURLsWithBackoff([null], performRequest, options, cancellationSignal);
|
|
264
|
-
}
|
package/dummy
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
This is an unnecessary file, just added to trigger the integration tests in a PR through GitHub actions.
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2015 CANAL+ Group
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { isOffline } from "../../../compat";
|
|
18
|
-
import {
|
|
19
|
-
CustomLoaderError,
|
|
20
|
-
isKnownError,
|
|
21
|
-
NetworkErrorTypes,
|
|
22
|
-
RequestError,
|
|
23
|
-
} from "../../../errors";
|
|
24
|
-
import log from "../../../log";
|
|
25
|
-
import cancellableSleep from "../../../utils/cancellable_sleep";
|
|
26
|
-
import getFuzzedDelay from "../../../utils/get_fuzzed_delay";
|
|
27
|
-
import TaskCanceller, {
|
|
28
|
-
CancellationSignal,
|
|
29
|
-
} from "../../../utils/task_canceller";
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Called on a loader error.
|
|
33
|
-
* Returns whether the loader request should be retried.
|
|
34
|
-
*
|
|
35
|
-
* TODO the notion of retrying or not could be transport-specific (e.g. 412 are
|
|
36
|
-
* mainly used for Smooth contents) and thus as part of the transport code (e.g.
|
|
37
|
-
* by rejecting with an error always having a `canRetry` property?).
|
|
38
|
-
* Or not, to ponder.
|
|
39
|
-
*
|
|
40
|
-
* @param {Error} error
|
|
41
|
-
* @returns {Boolean} - If true, the request can be retried.
|
|
42
|
-
*/
|
|
43
|
-
function shouldRetry(error : unknown) : boolean {
|
|
44
|
-
if (error instanceof RequestError) {
|
|
45
|
-
if (error.type === NetworkErrorTypes.ERROR_HTTP_CODE) {
|
|
46
|
-
return error.status >= 500 ||
|
|
47
|
-
error.status === 404 ||
|
|
48
|
-
error.status === 415 || // some CDN seems to use that code when
|
|
49
|
-
// requesting low-latency segments too much
|
|
50
|
-
// in advance
|
|
51
|
-
error.status === 412;
|
|
52
|
-
}
|
|
53
|
-
return error.type === NetworkErrorTypes.TIMEOUT ||
|
|
54
|
-
error.type === NetworkErrorTypes.ERROR_EVENT;
|
|
55
|
-
} else if (error instanceof CustomLoaderError) {
|
|
56
|
-
if (typeof error.canRetry === "boolean") {
|
|
57
|
-
return error.canRetry;
|
|
58
|
-
}
|
|
59
|
-
if (error.xhr !== undefined) {
|
|
60
|
-
return error.xhr.status >= 500 ||
|
|
61
|
-
error.xhr.status === 404 ||
|
|
62
|
-
error.xhr.status === 415 || // some CDN seems to use that code when
|
|
63
|
-
// requesting low-latency segments too much
|
|
64
|
-
// in advance
|
|
65
|
-
error.xhr.status === 412;
|
|
66
|
-
}
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
return isKnownError(error) && error.code === "INTEGRITY_ERROR";
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Returns true if we're pretty sure that the current error is due to the
|
|
74
|
-
* user being offline.
|
|
75
|
-
* @param {Error} error
|
|
76
|
-
* @returns {Boolean}
|
|
77
|
-
*/
|
|
78
|
-
function isOfflineRequestError(error : unknown) : boolean {
|
|
79
|
-
if (error instanceof RequestError) {
|
|
80
|
-
return error.type === NetworkErrorTypes.ERROR_EVENT &&
|
|
81
|
-
isOffline();
|
|
82
|
-
} else if (error instanceof CustomLoaderError) {
|
|
83
|
-
return error.isOfflineError;
|
|
84
|
-
}
|
|
85
|
-
return false; // under doubt, return false
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** Settings to give to the backoff functions to configure their behavior. */
|
|
89
|
-
export interface IBackoffSettings {
|
|
90
|
-
/**
|
|
91
|
-
* Initial delay to wait if a request fails before making a new request, in
|
|
92
|
-
* milliseconds.
|
|
93
|
-
*/
|
|
94
|
-
baseDelay : number;
|
|
95
|
-
/**
|
|
96
|
-
* Maximum delay to wait if a request fails before making a new request, in
|
|
97
|
-
* milliseconds.
|
|
98
|
-
*/
|
|
99
|
-
maxDelay : number;
|
|
100
|
-
/**
|
|
101
|
-
* Maximum number of retries to perform on "regular" errors (e.g. due to HTTP
|
|
102
|
-
* status, integrity errors, timeouts...).
|
|
103
|
-
*/
|
|
104
|
-
maxRetryRegular : number;
|
|
105
|
-
/**
|
|
106
|
-
* Maximum number of retries to perform when it appears that the user is
|
|
107
|
-
* currently offline.
|
|
108
|
-
*/
|
|
109
|
-
maxRetryOffline : number;
|
|
110
|
-
/** Callback called when a request is retried. */
|
|
111
|
-
onRetry : (err : unknown) => void;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const enum REQUEST_ERROR_TYPES { None,
|
|
115
|
-
Regular,
|
|
116
|
-
Offline }
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Guess the type of error obtained.
|
|
120
|
-
* @param {*} error
|
|
121
|
-
* @returns {number}
|
|
122
|
-
*/
|
|
123
|
-
function getRequestErrorType(error : unknown) : REQUEST_ERROR_TYPES {
|
|
124
|
-
return isOfflineRequestError(error) ? REQUEST_ERROR_TYPES.Offline :
|
|
125
|
-
REQUEST_ERROR_TYPES.Regular;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Specific algorithm used to perform segment and manifest requests.
|
|
130
|
-
*
|
|
131
|
-
* Here how it works:
|
|
132
|
-
*
|
|
133
|
-
* 1. You give it one or multiple URLs available for the resource you want to
|
|
134
|
-
* request (from the most important URL to the least important), the
|
|
135
|
-
* request callback itself, and some options.
|
|
136
|
-
*
|
|
137
|
-
* 2. it tries to call the request callback with the first URL:
|
|
138
|
-
* - if it works as expected, it resolves the returned Promise with that
|
|
139
|
-
* request's response.
|
|
140
|
-
* - if it fails, it calls ther `onRetry` callback given with the
|
|
141
|
-
* corresponding error and try with the next URL.
|
|
142
|
-
*
|
|
143
|
-
* 3. When all URLs have been tested (and failed), it decides - according to
|
|
144
|
-
* the error counters, configuration and errors received - if it can retry
|
|
145
|
-
* at least one of them, in the same order:
|
|
146
|
-
* - If it can, it increments the corresponding error counter, wait a
|
|
147
|
-
* delay (based on an exponential backoff) and restart the same logic
|
|
148
|
-
* for all retry-able URL.
|
|
149
|
-
* - If it can't it just reject the error through the returned Promise.
|
|
150
|
-
*
|
|
151
|
-
* Note that there are in fact two separate counters:
|
|
152
|
-
* - one for "offline" errors
|
|
153
|
-
* - one for other xhr errors
|
|
154
|
-
* Both counters are resetted if the error type changes from an error to the
|
|
155
|
-
* next.
|
|
156
|
-
*
|
|
157
|
-
* @param {Array.<string>} urls
|
|
158
|
-
* @param {Function} performRequest
|
|
159
|
-
* @param {Object} options - Configuration options.
|
|
160
|
-
* @param {Object} cancellationSignal
|
|
161
|
-
* @returns {Promise}
|
|
162
|
-
*/
|
|
163
|
-
export function tryURLsWithBackoff<T>(
|
|
164
|
-
urls : Array<string|null>,
|
|
165
|
-
performRequest : (
|
|
166
|
-
url : string | null,
|
|
167
|
-
cancellationSignal : CancellationSignal
|
|
168
|
-
) => Promise<T>,
|
|
169
|
-
options : IBackoffSettings,
|
|
170
|
-
cancellationSignal : CancellationSignal
|
|
171
|
-
) : Promise<T> {
|
|
172
|
-
if (cancellationSignal.isCancelled) {
|
|
173
|
-
return Promise.reject(cancellationSignal.cancellationError);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const { baseDelay,
|
|
177
|
-
maxDelay,
|
|
178
|
-
maxRetryRegular,
|
|
179
|
-
maxRetryOffline,
|
|
180
|
-
onRetry } = options;
|
|
181
|
-
let retryCount = 0;
|
|
182
|
-
let lastError = REQUEST_ERROR_TYPES.None;
|
|
183
|
-
|
|
184
|
-
const urlsToTry = urls.slice();
|
|
185
|
-
if (urlsToTry.length === 0) {
|
|
186
|
-
log.warn("Fetchers: no URL given to `tryURLsWithBackoff`.");
|
|
187
|
-
return Promise.reject(new Error("No URL to request"));
|
|
188
|
-
}
|
|
189
|
-
return tryURLsRecursively(urlsToTry[0], 0);
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Try to do the request of a given `url` which corresponds to the `index`
|
|
193
|
-
* argument in the `urlsToTry` Array.
|
|
194
|
-
*
|
|
195
|
-
* If it fails try the next one.
|
|
196
|
-
*
|
|
197
|
-
* If all URLs fail, start a timer and retry the first element in that array
|
|
198
|
-
* by following the configuration.
|
|
199
|
-
*
|
|
200
|
-
* @param {string|null} url
|
|
201
|
-
* @param {number} index
|
|
202
|
-
* @returns {Promise}
|
|
203
|
-
*/
|
|
204
|
-
async function tryURLsRecursively(
|
|
205
|
-
url : string | null,
|
|
206
|
-
index : number
|
|
207
|
-
) : Promise<T> {
|
|
208
|
-
try {
|
|
209
|
-
const res = await performRequest(url, cancellationSignal);
|
|
210
|
-
return res;
|
|
211
|
-
} catch (error : unknown) {
|
|
212
|
-
if (TaskCanceller.isCancellationError(error)) {
|
|
213
|
-
throw error;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (!shouldRetry(error)) {
|
|
217
|
-
// ban this URL
|
|
218
|
-
if (urlsToTry.length <= 1) { // This was the last one, throw
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// else, remove that element from the array and go the next URL
|
|
223
|
-
urlsToTry.splice(index, 1);
|
|
224
|
-
const newIndex = index >= urlsToTry.length - 1 ? 0 :
|
|
225
|
-
index;
|
|
226
|
-
onRetry(error);
|
|
227
|
-
if (cancellationSignal.isCancelled) {
|
|
228
|
-
throw cancellationSignal.cancellationError;
|
|
229
|
-
}
|
|
230
|
-
return tryURLsRecursively(urlsToTry[newIndex], newIndex);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const currentError = getRequestErrorType(error);
|
|
234
|
-
const maxRetry = currentError === REQUEST_ERROR_TYPES.Offline ? maxRetryOffline :
|
|
235
|
-
maxRetryRegular;
|
|
236
|
-
|
|
237
|
-
if (currentError !== lastError) {
|
|
238
|
-
retryCount = 0;
|
|
239
|
-
lastError = currentError;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (index < urlsToTry.length - 1) { // there is still URLs to test
|
|
243
|
-
const newIndex = index + 1;
|
|
244
|
-
onRetry(error);
|
|
245
|
-
if (cancellationSignal.isCancelled) {
|
|
246
|
-
throw cancellationSignal.cancellationError;
|
|
247
|
-
}
|
|
248
|
-
return tryURLsRecursively(urlsToTry[newIndex], newIndex);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Here, we were using the last element of the `urlsToTry` array.
|
|
252
|
-
// Increment counter and restart with the first URL
|
|
253
|
-
|
|
254
|
-
retryCount++;
|
|
255
|
-
if (retryCount > maxRetry) {
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
258
|
-
const delay = Math.min(baseDelay * Math.pow(2, retryCount - 1),
|
|
259
|
-
maxDelay);
|
|
260
|
-
const fuzzedDelay = getFuzzedDelay(delay);
|
|
261
|
-
const nextURL = urlsToTry[0];
|
|
262
|
-
onRetry(error);
|
|
263
|
-
if (cancellationSignal.isCancelled) {
|
|
264
|
-
throw cancellationSignal.cancellationError;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
await cancellableSleep(fuzzedDelay, cancellationSignal);
|
|
268
|
-
return tryURLsRecursively(nextURL, 0);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Lightweight version of the request algorithm, this time with only a simple
|
|
275
|
-
* Promise given.
|
|
276
|
-
* @param {Function} performRequest
|
|
277
|
-
* @param {Object} options
|
|
278
|
-
* @returns {Promise}
|
|
279
|
-
*/
|
|
280
|
-
export function tryRequestPromiseWithBackoff<T>(
|
|
281
|
-
performRequest : () => Promise<T>,
|
|
282
|
-
options : IBackoffSettings,
|
|
283
|
-
cancellationSignal : CancellationSignal
|
|
284
|
-
) : Promise<T> {
|
|
285
|
-
// same than for a single unknown URL
|
|
286
|
-
return tryURLsWithBackoff([null], performRequest, options, cancellationSignal);
|
|
287
|
-
}
|