Skip to content

Commit 90984f9

Browse files
committed
Update retry rules to require http status or timeout error (deprioritizes retry on parse errors)
1 parent 7cdbb32 commit 90984f9

7 files changed

+32
-14
lines changed

src/controller/audio-stream-controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ class AudioStreamController
515515
}
516516
const details = track.details as LevelDetails;
517517
if (!details) {
518-
this.warn('Audio track details are defined on fragment load progress');
518+
this.warn('Audio track details undefined on fragment load progress');
519519
return;
520520
}
521521
const audioCodec =

src/controller/base-stream-controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1397,7 +1397,7 @@ export default class BaseStreamController
13971397
} else if (retryConfig && errorAction) {
13981398
this.resetFragmentErrors(filterType);
13991399
if (retryCount < retryConfig.maxNumRetry) {
1400-
// Network retry is skipped for when level switch is preferred
1400+
// Network retry is skipped when level switch is preferred
14011401
errorAction.resolved = true;
14021402
} else {
14031403
logger.warn(

src/controller/error-controller.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
NetworkErrorAction,
88
} from '../errors';
99
import { PlaylistContextType, PlaylistLevelType } from '../types/loader';
10-
import { getRetryConfig, shouldRetry } from '../utils/error-helper';
10+
import {
11+
getRetryConfig,
12+
isTimeoutError,
13+
shouldRetry,
14+
} from '../utils/error-helper';
1115
import { HdcpLevels } from '../types/level';
1216
import { logger } from '../utils/logger';
1317
import type Hls from '../hls';
@@ -187,7 +191,12 @@ export default class ErrorController implements NetworkComponentAPI {
187191
const retryConfig = getRetryConfig(hls.config.playlistLoadPolicy, data);
188192
const retryCount = this.playlistError++;
189193
const httpStatus = data.response?.code;
190-
const retry = shouldRetry(retryConfig, retryCount, httpStatus);
194+
const retry = shouldRetry(
195+
retryConfig,
196+
retryCount,
197+
isTimeoutError(data),
198+
httpStatus
199+
);
191200
if (retry) {
192201
return {
193202
action: NetworkErrorAction.RetryRequest,
@@ -232,7 +241,12 @@ export default class ErrorController implements NetworkComponentAPI {
232241
if (level) {
233242
level.fragmentError++;
234243
const httpStatus = data.response?.code;
235-
const retry = shouldRetry(retryConfig, fragmentErrors, httpStatus);
244+
const retry = shouldRetry(
245+
retryConfig,
246+
fragmentErrors,
247+
isTimeoutError(data),
248+
httpStatus
249+
);
236250
if (retry) {
237251
return {
238252
action: NetworkErrorAction.RetryRequest,

src/types/loader.ts

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export interface LoaderResponse {
6464
url: string;
6565
data?: string | ArrayBuffer | Object;
6666
// Errors can include HTTP status code and error message
67+
// Successful responses should include status code 200
6768
code?: number;
6869
text?: string;
6970
}

src/utils/error-helper.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,17 @@ export function getLoaderConfigWithoutReties(
4949
export function shouldRetry(
5050
retryConfig: RetryConfig | null | undefined,
5151
retryCount: number,
52+
isTimeout: boolean,
5253
httpStatus?: number | undefined
5354
): retryConfig is RetryConfig & boolean {
5455
return (
5556
!!retryConfig &&
5657
retryCount < retryConfig.maxNumRetry &&
57-
retryForHttpStatus(httpStatus)
58+
(retryForHttpStatus(httpStatus) || !!isTimeout)
5859
);
5960
}
6061

6162
export function retryForHttpStatus(httpStatus: number | undefined) {
62-
return (
63-
httpStatus === undefined ||
64-
(httpStatus !== 0 && (httpStatus < 400 || httpStatus > 499))
65-
);
63+
// Do not retry on status 4xx, status 0 (CORS error), or undefined (decrypt/gap/parse error)
64+
return !!httpStatus && (httpStatus < 400 || httpStatus > 499);
6665
}

src/utils/fetch-loader.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
LoaderStats,
66
LoaderConfiguration,
77
LoaderOnProgress,
8+
LoaderResponse,
89
} from '../types/loader';
910
import { LoadStats } from '../loader/load-stats';
1011
import ChunkCache from '../demux/chunk-cache';
@@ -151,9 +152,10 @@ class FetchLoader implements Loader<LoaderContext> {
151152
stats.loaded = stats.total = total;
152153
}
153154

154-
const loaderResponse = {
155+
const loaderResponse: LoaderResponse = {
155156
url: response.url,
156157
data: responseData,
158+
code: response.status,
157159
};
158160

159161
if (onProgress && !Number.isFinite(config.highWaterMark)) {

src/utils/xhr-loader.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
LoaderStats,
66
Loader,
77
LoaderConfiguration,
8+
LoaderResponse,
89
} from '../types/loader';
910
import { LoadStats } from '../loader/load-stats';
1011
import { RetryConfig } from '../config';
@@ -197,17 +198,18 @@ class XhrLoader implements Loader<LoaderContext> {
197198
if (!this.callbacks) {
198199
return;
199200
}
200-
const response = {
201+
const response: LoaderResponse = {
201202
url: xhr.responseURL,
202203
data: data,
204+
code: status,
203205
};
204206

205207
this.callbacks.onSuccess(response, stats, context, xhr);
206208
} else {
207209
const retryConfig = config.loadPolicy.errorRetry;
208210
const retryCount = stats.retry;
209211
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
210-
if (shouldRetry(retryConfig, retryCount, status)) {
212+
if (shouldRetry(retryConfig, retryCount, false, status)) {
211213
this.retry(retryConfig);
212214
} else {
213215
logger.error(`${status} while loading ${context.url}`);
@@ -226,7 +228,7 @@ class XhrLoader implements Loader<LoaderContext> {
226228
loadtimeout(): void {
227229
const retryConfig = this.config?.loadPolicy.timeoutRetry;
228230
const retryCount = this.stats.retry;
229-
if (shouldRetry(retryConfig, retryCount)) {
231+
if (shouldRetry(retryConfig, retryCount, true)) {
230232
this.retry(retryConfig);
231233
} else {
232234
logger.warn(`timeout while loading ${this.context.url}`);

0 commit comments

Comments
 (0)