Mega-Debrid: schnelle API-Aufloesung darf langsame Web-Aufloesung ueberlappen (Single-Account-Durchsatz)
Bei nur einem Mega-Debrid-Account war die Link-Aufloesung global seriell: getSerializedValidatingLimit = max(1, nutzbare Accounts) = 1. Da ~die Haelfte der Rapidgator-Links von der Mega-API faelschlich als "Fichier supprimé" abgelehnt wird (bestaetigt: die offizielle Mega-Debrid-Download-Station- Integration nutzt dieselbe getLink-API voellig ohne Fallback), fallen sie auf den Web-Pfad, der pro Account zwingend single-flight ist (eine Web-Session = ein Request). Eine langsame/haengende Web-Aufloesung (live 11s gesehen, im Extremfall bis zum 60s-Timeout) hielt so den einzigen Aufloesungs-Slot und liess die Download-Slots leerlaufen (live gemessen: active faellt von 8 auf 2, Tempo von ~183 auf 71 MB/s, obwohl hunderte Items warteten). Fix: der Scheduler erlaubt jetzt pro Account EINE zusaetzliche gleichzeitige Aufloesung, solange bereits eine im (langsamen) Web-Pfad steckt - so zieht eine schnelle API-Aufloesung (~0.6s) an einer haengenden Web-Aufloesung vorbei statt dahinter zu warten. Es entstehen NIE zwei gleichzeitige API-Aufrufe pro Account: die Aufweitung greift nur, wenn megaDebridInFlight im Web-Modus aktiv ist (der erste also nicht mehr in der API-Phase), und der synchron in startItem gesetzte validating-Status begrenzt die Gesamtzahl race-frei auf 1 API + 1 Web pro Account. Skaliert mit mehr Accounts auf N+N - der sauberste Hebel bleibt, weitere Accounts hinzuzufuegen (parallele Web-Queues). getMegaDebridInFlightCountForMode liest die bestehenden :web-Zaehler; shouldDelayStartForItem nutzt sie nur zum Aufweiten der Obergrenze, nie zum Verschaerfen. Tests: 4 Faelle (Erststart frei / kein zweiter API waehrend API-Phase / Overlap sobald Web-Phase aktiv / Deckel bei 1 API + 1 Web).
This commit is contained in:
@@ -339,6 +339,25 @@ export function resetMegaDebridRuntimeStateForTests(): void {
|
||||
megaDebridInFlight.clear();
|
||||
}
|
||||
|
||||
export function getMegaDebridInFlightCountForMode(mode: "api" | "web"): number {
|
||||
const suffix = `:${mode}`;
|
||||
let total = 0;
|
||||
for (const [key, count] of megaDebridInFlight) {
|
||||
if (key.endsWith(suffix)) {
|
||||
total += count;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
export function primeMegaDebridInFlightForTests(key: string, count: number): void {
|
||||
if (count <= 0) {
|
||||
megaDebridInFlight.delete(key);
|
||||
return;
|
||||
}
|
||||
megaDebridInFlight.set(key, count);
|
||||
}
|
||||
|
||||
export function pruneExpiredMegaDebridRuntimeState(now = Date.now()): number {
|
||||
let removed = 0;
|
||||
const grace = 60 * 60 * 1000;
|
||||
|
||||
@@ -52,7 +52,7 @@ function releaseTlsSkip(): void {
|
||||
}
|
||||
import { cleanupCancelledPackageArtifactsAsync, removeDownloadLinkArtifacts, removeSampleArtifacts } from "./cleanup";
|
||||
import { planDownloadCompletion, reconcileFinalizedSize, validateDownloadedFileCompletion } from "./download-completion";
|
||||
import { AllDebridWebUnrestrictor, BestDebridWebUnrestrictor, DebridService, MegaWebUnrestrictor, RealDebridWebUnrestrictor, checkRapidgatorOnline, fetchAllDebridHostInfo, getAvailableDebridLinkApiKeys, getAvailableMegaDebridAccounts, getMegaDebridAccountCooldownState, pruneExpiredDebridLinkRuntimeState, pruneExpiredMegaDebridRuntimeState } from "./debrid";
|
||||
import { AllDebridWebUnrestrictor, BestDebridWebUnrestrictor, DebridService, MegaWebUnrestrictor, RealDebridWebUnrestrictor, checkRapidgatorOnline, fetchAllDebridHostInfo, getAvailableDebridLinkApiKeys, getAvailableMegaDebridAccounts, getMegaDebridAccountCooldownState, getMegaDebridInFlightCountForMode, pruneExpiredDebridLinkRuntimeState, pruneExpiredMegaDebridRuntimeState } from "./debrid";
|
||||
import { cleanupArchives, clearExtractResumeState, collectArchiveCleanupTargets, detectArchiveSignature, extractPackageArchives, findArchiveCandidates, hasAnyFilesRecursive, removeEmptyDirectoryTree, resetExtractorCachesForPasswordChange, type ExtractArchiveFailureInfo } from "./extractor";
|
||||
import { validateFileAgainstManifest } from "./integrity";
|
||||
import { classifyDiskError } from "./fs-error";
|
||||
@@ -8212,7 +8212,13 @@ export class DownloadManager extends EventEmitter {
|
||||
const provider = resolveMegaDebridProvider(this.settings, this.getExpectedProviderForItem(item));
|
||||
const serializedValidatingLimit = this.getSerializedValidatingLimit(provider);
|
||||
if (provider && Number.isFinite(serializedValidatingLimit) && serializedValidatingLimit < Number.MAX_SAFE_INTEGER) {
|
||||
return this.getProviderValidatingTaskCount(provider, item.id) >= serializedValidatingLimit;
|
||||
const validating = this.getProviderValidatingTaskCount(provider, item.id);
|
||||
if (provider === "megadebrid-api") {
|
||||
const webInFlight = getMegaDebridInFlightCountForMode("web");
|
||||
const overlapAllowance = Math.min(serializedValidatingLimit, webInFlight);
|
||||
return validating >= serializedValidatingLimit + overlapAllowance;
|
||||
}
|
||||
return validating >= serializedValidatingLimit;
|
||||
}
|
||||
if (provider !== "alldebrid") {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user