mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
68 lines
3.2 KiB
JavaScript
68 lines
3.2 KiB
JavaScript
import { computed, peek } from "../../core/signals/primitives.js";
|
|
import { defineBehavior } from "../../core/composition/create-composition.js";
|
|
import { createMachineReactor } from "../../core/reactors/create-machine-reactor.js";
|
|
import { isResolvedPresentation } from "../../media/types/index.js";
|
|
import { getCdnId, getOrderedCdnIds } from "../../media/utils/cdn.js";
|
|
//#region src/playback/behaviors/derive-cdn-priority.ts
|
|
/**
|
|
* **Session-level CDN priority.** While a presentation is resolved, owns the
|
|
* `cdnPriority` signal: the distinct CDNs the source is served from (origin of
|
|
* each track's URL), in manifest priority order — most-preferred first. Cleared
|
|
* on src unload. The name mirrors HLS content steering's `PATHWAY-PRIORITY`.
|
|
*
|
|
* Redundant-stream sources (e.g. Mux's `?redundant_streams=true`) list the same
|
|
* content on multiple hosts, so the candidate tracks already include one variant
|
|
* per CDN. This behavior publishes *which* CDNs exist and their priority; the
|
|
* `preferActiveCdn` scope rule in `track-switching` reads `cdnPriority` and
|
|
* narrows each type's candidates to the first CDN with surviving tracks — so
|
|
* video / audio / text all resolve from one host (the shared list is the
|
|
* per-presentation coherence guarantee).
|
|
*
|
|
* The "active" CDN is not stored — it's derived by the scope as the
|
|
* highest-priority entry in `cdnPriority` that still has tracks after the
|
|
* constraints pre-pass. That makes failover a pure consequence of the (future)
|
|
* failed-CDN constraint: when the primary's tracks are pruned during cooldown,
|
|
* the scope falls to the next CDN; when the primary recovers, it snaps back.
|
|
* Content steering, when it lands, reorders `cdnPriority` (pathway priority as a
|
|
* sort key).
|
|
*
|
|
* Lifecycle: `'presentation-unresolved'` ↔ `'presentation-resolved'`, mirroring
|
|
* `setupTrackSwitching`. The resolved state owns the signal; its entry-returned
|
|
* cleanup clears it on exit (canonical cleanup-binds-to-setup per `reactors.md`).
|
|
*/
|
|
const samePriority = (a, b) => !!a && a.length === b.length && a.every((cdn, i) => cdn === b[i]);
|
|
/**
|
|
* Manage `cdnPriority`: publish the manifest-ordered CDN list on src load, clear
|
|
* on src unload.
|
|
*
|
|
* @example
|
|
* const reactor = deriveCdnPriority.setup({ state });
|
|
*/
|
|
const deriveCdnPriority = defineBehavior({
|
|
stateKeys: ["presentation", "cdnPriority"],
|
|
contextKeys: [],
|
|
setup: ({ state, config = {} }) => {
|
|
const getCdnId$1 = config.getCdnId ?? getCdnId;
|
|
const derivedStateSignal = computed(() => isResolvedPresentation(state.presentation.get()) ? "presentation-resolved" : "presentation-unresolved");
|
|
return createMachineReactor({
|
|
initial: "presentation-unresolved",
|
|
monitor: () => derivedStateSignal.get(),
|
|
states: {
|
|
"presentation-unresolved": {},
|
|
"presentation-resolved": {
|
|
entry: () => () => state.cdnPriority.set(void 0),
|
|
effects: [() => {
|
|
const presentation = state.presentation.get();
|
|
if (!isResolvedPresentation(presentation)) return;
|
|
const next = getOrderedCdnIds(presentation, getCdnId$1);
|
|
if (!samePriority(peek(state.cdnPriority), next)) state.cdnPriority.set(next);
|
|
}]
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
//#endregion
|
|
export { deriveCdnPriority };
|
|
|
|
//# sourceMappingURL=derive-cdn-priority.js.map
|