Fix: Provider-Cooldown-Fallback fuehrt die Kette jetzt wirklich mit dem Ersatz-Provider an (Routing-Slice)
Wenn ein Provider in den Manager-Cooldown laeuft (>=20 Fehler in Folge) und auto-Fallback aktiv ist, berechnete der Manager zwar einen Ersatz-Provider (findFallbackProviderNotInCooldown), warf ihn dann aber weg: der unrestrictLink- Aufruf bekam keinen Hint, also baute debrid.ts die Provider-Kette frisch aus providerOrder und fuehrte erneut mit dem ausgebremsten Provider 1 an — ein meist in den 60s-Timeout laufender, verschwendeter Versuch, bevor ueberhaupt der gesunde Provider drankam. Jetzt wird der Ersatz-Provider als bevorzugter Lead durchgereicht. Die Kette wird UMSORTIERT, nicht beschnitten: der ausgebremste Provider bleibt als letzter Notnagel in der Reihenfolge, sodass kein Link gestrandet werden kann. Sind ALLE Provider im Cooldown, erreicht der Aufruf unrestrictLink ohnehin nicht (der else-Zweig queued einen Retry). Greift damit nur, wenn ein Provider bereits nachweislich degradiert ist — strikt besser, wenn aktiv, und ohne Timeout-, Cancel- oder Budget-Vertrag anzufassen. - debrid.ts: reine leadProviderChainWith(order, preferred) (export) + optionaler 4. Param preferredLeadProvider an unrestrictLink; Reorder direkt nach Aufbau der Reihenfolge. - download-manager.ts: Ersatz-Provider in preferredLeadProvider festhalten und an den unrestrictLink-Aufruf durchreichen. - Tests: Integration (ohne Hint fuehrt realdebrid, mit Hint fuehrt debridlink) + drei reine Helper-Tests fuer die No-Stranding-Invariante. Zwei verbleibende HIGH-Punkte sind bewusst NICHT autonom geaendert, sondern als Produkt-/UI-Entscheidung in tasks/entscheidungen-offen.md vorgelegt (globaler 60s-Failover-Timeout; gespiegelter Mega API/Web-Schalter).
This commit is contained in:
+10
-2
@@ -1321,6 +1321,13 @@ function toProviderOrder(primary: DebridProvider, secondary: DebridFallbackProvi
|
||||
return uniqueProviderOrder(order);
|
||||
}
|
||||
|
||||
export function leadProviderChainWith(order: readonly DebridProvider[], preferred: DebridProvider | null | undefined): DebridProvider[] {
|
||||
if (!preferred || !order.includes(preferred)) {
|
||||
return [...order];
|
||||
}
|
||||
return [preferred, ...order.filter((provider) => provider !== preferred)];
|
||||
}
|
||||
|
||||
function isRapidgatorLink(link: string): boolean {
|
||||
try {
|
||||
const hostname = new URL(link).hostname.toLowerCase();
|
||||
@@ -3700,7 +3707,7 @@ export class DebridService {
|
||||
return `${PROVIDER_LABELS[effectiveProvider]} Tageslimit erreicht`;
|
||||
}
|
||||
|
||||
public async unrestrictLink(link: string, signal?: AbortSignal, settingsSnapshot?: AppSettings): Promise<ProviderUnrestrictedLink> {
|
||||
public async unrestrictLink(link: string, signal?: AbortSignal, settingsSnapshot?: AppSettings, preferredLeadProvider?: DebridProvider | null): Promise<ProviderUnrestrictedLink> {
|
||||
const settings = settingsSnapshot ? cloneSettings(settingsSnapshot) : cloneSettings(this.settings);
|
||||
|
||||
const routing = settings.hosterRouting || {};
|
||||
@@ -3777,9 +3784,10 @@ export class DebridService {
|
||||
}
|
||||
}
|
||||
|
||||
const order: DebridProvider[] = (settings.providerOrder && settings.providerOrder.length > 0)
|
||||
const baseOrder: DebridProvider[] = (settings.providerOrder && settings.providerOrder.length > 0)
|
||||
? uniqueProviderOrder(settings.providerOrder)
|
||||
: toProviderOrder(settings.providerPrimary, settings.providerSecondary, settings.providerTertiary);
|
||||
const order = leadProviderChainWith(baseOrder, preferredLeadProvider);
|
||||
|
||||
const primary = order[0];
|
||||
if (!settings.autoProviderFallback) {
|
||||
|
||||
Reference in New Issue
Block a user