npaw-plugin-nwf
Version:
NPAW's Plugin
193 lines (192 loc) • 7.79 kB
TypeScript
import { VideoSegment } from '../Storage/VideoSegment';
import { CdnRequestStatus } from '../Utils/Constants';
import type { SyntheticCdnStats } from '../Utils/Constants';
import BalancerOptions from '../Utils/Options';
import Cdn from './Cdn';
import Emitter from '../Utils/Emitter';
import Resource from '../Resource/Resource';
import P2PLoader from './P2PLoader';
/**
* @class
* @description Class controlling the requests from the player to CDNs.
* It has different algorithms to choose to decide which CDN has to be used for every request.
* @exports CDNLoader
*/
export default class CDNLoader extends Emitter {
private _p2pLoader;
private _secure?;
private _method?;
private _activeSwitching?;
private _probeOnBanned?;
private _noProbing?;
private _bandwidthThreshold;
private _responseUUID?;
private _options;
private _cdnList;
private _activeCdnRequests;
private _activeRequests;
private _failedRequests;
private _syntheticCdnStats;
private _chunkCount;
private _probingInfo;
private _highestChunkBandwidth;
private _highestRenditionBandwidth;
private _cdnLastInstantBandwith;
private _cdnInstantBandwith;
private _cdnPeakBandwidth;
private _retries;
private _totalDownloadedBytes;
private _firstRequestTime;
private _lastChunkTime;
private _lastChunksLapse;
private _resource;
currentRenditionBandwidth: number;
currentRenditionPos: number;
renditionCount: number;
initializated: boolean;
monitoringStarted: boolean;
lastUsedCdn?: string;
private _lastSuccessfulVideoProvider?;
codavelAllBanned: boolean;
codavelBanCount: number;
codavelUnbanCount: number;
codavelBanTime: number;
codavelUnbanTime: number;
codavelSwitches: number;
codavelSwitchesDueToConnectivity: number;
codavelSwitchesDueToErrors: number;
codavelSwitchesDueToQuality: number;
codavelBanRefTicToc: number;
lastCodavelRequestStatus: CdnRequestStatus;
private codavelProvidersState;
processedApiCall: boolean;
avgApiCallResponseTime?: number;
minApiCallResponseTime?: number;
maxApiCallResponseTime?: number;
apiCallErrors?: number;
apiCallResponses?: number;
p2pAvailable: boolean;
bolinaAvailable: boolean;
activeSwitchingPriority: string;
priorityCdn: string;
announcedCdns: number;
/**
* Long-lived "last failed trial" marker (PR9 / Android
* `ActiveSwitcher.lastFailedTrialProvider`, `plugin-android@56bf3e20`).
* Set by `Loader.onProcessSegmentFail` when a tagged trial segment ends in
* failure; consumed and cleared by the next `_getCdnToProbe` sort. Lives
* on CDNLoader because `CDNSelectorBusinessObject` is reinstantiated per
* `updateUrl` call and would otherwise lose the marker between segments.
*/
private _lastFailedTrialCdn;
segmentDuration?: number;
private apiHost;
/**
* Constructs CDNLoader
* @param {BalancerOptions} options Options object.
*/
constructor(options: BalancerOptions, resource: Resource, loader: P2PLoader, apiHost: string);
getSecure(): boolean;
getActiveRequests(): Map<string, VideoSegment>;
gotEmptyResponse(): void;
/**
* For initial workflow and resets, asks to the API for the list of available
* CDNs with the content we want to reproduce.
* It creates the CDN list object and fills it with the CDNs received.
* Also calculates the relative score.
* @public
*/
setSettings(resp: balancerResponse, originalHost: string): void;
private updateSettings;
/**
* Resolve the four-timeout values from /decision and push them into
* CDNDefaultSettings so the XHR layer reads a single source. Priority:
* 1. customData.cdnTimeout.X (Android-shape nested response)
* 2. BalancerOptions.cdnTimeout.X (constructor or dotted customData.options)
* 3. customData.cdnTimeout.requestTimeoutMilliseconds (legacy alias for callTimeout)
* 4. previous CDNDefaultSettings value (default or last decision)
*/
private _applyCdnTimeoutSettings;
startMonitoring(): void;
updateCDNStatsOnFailure(cdnName: string, segment: VideoSegment): void;
removeActiveSegment(segment: VideoSegment): void;
updateCDNStatsOnSuccess(segment: VideoSegment): void;
/**
* Android parity (ProviderLoader.trackSwitch): count P2P->CDN switches only
* when the previously successful video provider was actually P2P. The state
* is consumed on first fallback so concurrent retries do not inflate
* switches before a new successful provider is established.
*/
consumeLastSuccessfulP2PProvider(): boolean;
getCdnList(): Map<string, Cdn>;
/**
* Record that the last trial fetch on `cdnName` ended in failure so the
* next `_getCdnToProbe` selection skips that CDN. Android parity (PR9 /
* `plugin-android@56bf3e20`): set by `Loader.onProcessSegmentFail` when the
* failing segment carried a `trialTag`; the next sort consumes and clears
* the marker, so it represents "the most recent failed trial" only — not
* a persistent blacklist.
*/
markLastFailedTrial(cdnName: string): void;
/** Test hook — production callers should not need to read this. */
getLastFailedTrialCdn(): Cdn | null;
getSyntheticCdnStats(): {
BYPASS: SyntheticCdnStats;
BLACKLIST: SyntheticCdnStats;
ORIGIN: SyntheticCdnStats;
};
/**
* Snapshot + reset. Kept the legacy name so external callers (tests, other
* packages) keep compiling; returns the full SyntheticCdnStats shape now.
*/
consumeSyntheticCdnCounts(): {
BYPASS: SyntheticCdnStats;
BLACKLIST: SyntheticCdnStats;
ORIGIN: SyntheticCdnStats;
};
/**
* Android parity (StatsCollector.kt:549, wrapSyntheticResponse). Accumulate
* the response metrics from a completed XHR into the synthetic CDN bucket
* tagged on the segment. Only records when bytes > 0 on success (Android
* Balancer.kt:358) — no response body means nothing to report.
*/
private _recordSyntheticResponse;
private _bumpHttpBucket;
updateProgressStats(): void;
private getSignedUrlFromApi;
updateUrl(segment: VideoSegment, isProbe?: boolean, cdnName?: string): string | undefined;
setResourceInfo(url: string): void;
getRecommendedManifest(): Promise<string>;
/**
* Returns an object with the CDN data stats of the current content/view.
* @returns {CdnLoaderStats} CDN info object.
* @public
*/
getStats(): CdnLoaderStats;
/**
* CAUTION: if you try to disable many CDN you may break the view!
* Enables/disables the use of a specific CDN.
* You can get the name of the CDNs using getStats().cdn
* @param {string} name Cdn name to be disabled/enabled.
* @param {boolean} mode True to enable, False to disable.
* @returns {boolean} True if change was applied, false if not.
* @public
*/
changeStatusCDN(name: string, enable: boolean): boolean;
setMaxBandwidth(name: string, bandwidth: number): boolean;
getMaxBandwidth(cdnName: string): number;
updateCodavelBanTimes(): void;
resetOnPing(): void;
onCodavelSwitched(): void;
onCodavelSucessfullResponse(): void;
onCodavelFailedResponse(status: CdnRequestStatus): void;
onFailedApiResponse(): void;
onSucessfullApiResponse(responseTime: number): void;
getBucket(): string | undefined;
getIsLive(): boolean | undefined;
getForceDecision(): boolean | undefined;
getSegmentDuration(): number | undefined;
private isNotOnCdnList;
private isNotOnWhitelist;
private isOnUrlBlacklist;
}