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