UNPKG

rx-player

Version:
124 lines (123 loc) 5.07 kB
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, }; }