rx-player
Version:
Canal+ HTML5 Video Player
124 lines (123 loc) • 5.07 kB
JavaScript
import config from "../../../config";
import { formatError } from "../../../errors";
import log from "../../../log";
import objectAssign from "../../../utils/object_assign";
import { CancellationError } from "../../../utils/task_canceller";
import errorSelector from "../utils/error_selector";
import { scheduleRequestWithCdns } from "../utils/schedule_request";
/**
* Create an `IThumbnailFetcher` object which will allow to easily fetch and parse
* segments.
* An `IThumbnailFetcher` also implements a retry mechanism, based on the given
* `requestOptions` argument, which may retry a segment request when it fails.
*
* @param {Object} pipeline
* @param {Object|null} cdnPrioritizer
* @returns {Function}
*/
export default function createThumbnailFetcher(
/** The transport-specific logic allowing to load thumbnails. */
pipeline,
/**
* Abstraction allowing to synchronize, update and keep track of the
* priorization of the CDN to use to load any given segment, in cases where
* multiple ones are available.
*
* Can be set to `null` in which case a minimal priorization logic will be used
* instead.
*/
cdnPrioritizer) {
const { loadThumbnail } = pipeline;
// TODO short-lived cache?
/**
* Fetch a specific segment.
* @param {Object} thumbnail
* @param {Object} thumbnailTrack
* @param {Object} requestOptions
* @param {Object} cancellationSignal
* @returns {Promise}
*/
return async function fetchThumbnail(thumbnail, thumbnailTrack, requestOptions, cancellationSignal) {
let connectionTimeout;
if (requestOptions.connectionTimeout === undefined ||
requestOptions.connectionTimeout < 0) {
connectionTimeout = undefined;
}
else {
connectionTimeout = requestOptions.connectionTimeout;
}
const pipelineRequestOptions = {
timeout: requestOptions.requestTimeout < 0 ? undefined : requestOptions.requestTimeout,
connectionTimeout,
cmcdPayload: undefined,
};
log.debug("TF: Beginning thumbnail request", thumbnail.time);
cancellationSignal.register(onCancellation);
let res;
try {
res = await scheduleRequestWithCdns(thumbnailTrack.cdnMetadata, cdnPrioritizer, callLoaderWithUrl, objectAssign({ onRetry }, requestOptions), cancellationSignal);
if (cancellationSignal.isCancelled()) {
return Promise.reject(cancellationSignal.cancellationError);
}
log.debug("TF: Thumbnail request ended with success", thumbnail.time);
cancellationSignal.deregister(onCancellation);
}
catch (err) {
cancellationSignal.deregister(onCancellation);
if (err instanceof CancellationError) {
log.debug("TF: Thumbnail request aborted", thumbnail.time);
throw err;
}
log.debug("TF: Thumbnail request failed", thumbnail.time);
throw errorSelector(err);
}
try {
const parsed = pipeline.parseThumbnail(res.responseData, {
thumbnail,
thumbnailTrack,
});
return parsed;
}
catch (error) {
throw formatError(error, {
defaultCode: "PIPELINE_PARSE_ERROR",
defaultReason: "Unknown parsing error",
});
}
function onCancellation() {
log.debug("TF: Thumbnail request cancelled", thumbnail.time);
}
/**
* Call a segment loader for the given URL with the right arguments.
* @param {Object|null} cdnMetadata
* @returns {Promise}
*/
function callLoaderWithUrl(cdnMetadata) {
return loadThumbnail(cdnMetadata, thumbnail, pipelineRequestOptions, cancellationSignal);
}
/**
* Function called when the function request is retried.
* @param {*} err
*/
function onRetry(err) {
const formattedErr = errorSelector(err);
log.warn("TF: Thumbnail request retry ", thumbnail.time, formattedErr);
}
};
}
/**
* @param {Object} baseOptions
* @returns {Object}
*/
export function getThumbnailFetcherRequestOptions({ maxRetry, requestTimeout, connectionTimeout, }) {
const { DEFAULT_MAX_THUMBNAIL_REQUESTS_RETRY_ON_ERROR, DEFAULT_THUMBNAIL_REQUEST_TIMEOUT, DEFAULT_THUMBNAIL_CONNECTION_TIMEOUT, INITIAL_BACKOFF_DELAY_BASE, MAX_BACKOFF_DELAY_BASE, } = config.getCurrent();
return {
maxRetry: maxRetry !== null && maxRetry !== void 0 ? maxRetry : DEFAULT_MAX_THUMBNAIL_REQUESTS_RETRY_ON_ERROR,
baseDelay: INITIAL_BACKOFF_DELAY_BASE.REGULAR,
maxDelay: MAX_BACKOFF_DELAY_BASE.REGULAR,
requestTimeout: requestTimeout === undefined ? DEFAULT_THUMBNAIL_REQUEST_TIMEOUT : requestTimeout,
connectionTimeout: connectionTimeout === undefined
? DEFAULT_THUMBNAIL_CONNECTION_TIMEOUT
: connectionTimeout,
};
}