Files
v10/dist/default/playback/primitives/failover-fetch.js
T

42 lines
1.9 KiB
JavaScript

import { update } from "../../core/signals/primitives.js";
import { findTrackById } from "../../media/utils/tracks.js";
import { addFailedCdn, getCdnId } from "../../media/utils/cdn.js";
//#region src/playback/primitives/failover-fetch.ts
/**
* Decorate a fetch so a failed request trips the **selected track's** CDN into
* `failedCdns`. The decorated fetch's type is preserved, so this wraps both
* `resolve-track`'s playlist `FetchText` and the segment loaders' `FetchBytes`.
*
* The CDN id comes from the selected track's media-playlist URL, never the
* failed addressable: a segment URL resolves relative to its playlist and, per
* RFC 3986, drops the playlist's query string (`…/r.m3u8?cdn=fastly` → `…/0.ts`),
* so a query-keyed `getCdnId` (e.g. Mux's `cdn=`) keyed on it would derive an id
* that never matches the ones `deriveCdnPriority` / track-switching build from
* `track.url`. The in-flight fetch belongs to the selected track — a source or
* track switch aborts it, and aborts don't trip — so the selected track is the
* right CDN to fail over. For `resolve-track` the resolving track *is* the
* selected track, so this is identical to keying on its addressable.
*
* No-op when no failover monitor is composed (it owns the signal) or the
* selected track can't be located.
*/
function failoverFetch(baseFetch, state, config) {
const getCdnId$1 = config.getCdnId ?? getCdnId;
return (async (addressable, options) => {
try {
return await baseFetch(addressable, options);
} catch (error) {
if (!options?.signal?.aborted && state.failedCdns) {
const presentation = state.presentation.get();
const trackId = state[config.selectedKey].get();
const track = presentation && trackId ? findTrackById(presentation, trackId) : void 0;
if (track) update(state.failedCdns, (cdns) => addFailedCdn(cdns, getCdnId$1(track.url)));
}
throw error;
}
});
}
//#endregion
export { failoverFetch };
//# sourceMappingURL=failover-fetch.js.map