Fix: Langsame Mega-Accounts bremsen nicht mehr die ganze Umwandlungs-Queue (Latenz-Demotion)
Folge-Fix zu v1.7.197 (Round-Robin): User meldete direkt nach dem Update deutlich langsamere Link-Umwandlung. Ursache: MegaWebFallback.runExclusive ist eine GLOBALE Single-Flight-Queue — alle Umwandlungen laufen seriell. Vor v1.7.197 liefen praktisch alle Links ueber denselben warmen, schnellen Account (~800ms); das Round-Robin mischte nun auch die zuvor nie genutzten Accounts in die Reihe. Ist einer davon langsam (kalte Session, traegere Server, abgelaufenes Premium), blockiert seine Umwandlung in der seriellen Queue ALLE nachfolgenden Links — gefuehlt wird alles langsam. Fix: Pro Account+Modus wird ein EMA (0.7/0.3) der erfolgreichen Unrestrict-Dauer gefuehrt. Bei jeder Aufloesung wird die Round-Robin- Reihenfolge partitioniert: Accounts, deren EMA ueber max(6s, 3x bestes verfuegbares EMA) liegt, wandern ans Ende der Reihe — sie bleiben Failover-Reserve (werden weiter genutzt, wenn die schnellen am Limit/Cooldown sind), laufen aber nicht mehr in der gleichmaessigen Verteilung mit. Ungemessene Accounts gelten als gesund (bekommen ihre Chance und damit ein EMA). Erholt sich ein Account (relativer Threshold), rotiert er automatisch wieder mit. Schon nach EINEM langsamen Erfolg ist ein Bremser-Account aus der Verteilung draussen. Fehlschlaege werden wie bisher ueber die bestehenden Cooldowns behandelt. Diagnose-Sichtbarkeit: das TEST-Event im account-rotation.log traegt jetzt emaMs und slow=true, damit ein gebremster Account sofort erkennbar ist. 2 neue Regressionstests (langsamer Account wird depriorisiert; bleibt Failover-Reserve wenn die schnellen gesperrt sind). Suite 808 gruen, tsc=6 Baseline, self-check + build ok.
This commit is contained in:
+79
-1
@@ -3,7 +3,7 @@ import { defaultSettings, REQUEST_RETRIES } from "../src/main/constants";
|
||||
import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys";
|
||||
import { getMegaDebridAccountId } from "../src/shared/mega-debrid-accounts";
|
||||
import { getProviderUsageDayKey } from "../src/shared/provider-daily-limits";
|
||||
import { clearMegaDebridEmptyResponseStreak, DebridService, extractRapidgatorFilenameFromHtml, fetchAllDebridHostInfo, fetchDebridLinkHostLimits, filenameFromRapidgatorUrlPath, getDebridLinkKeyRuntimeStateForTests, getMegaDebridAccountCooldownState, MEGA_DEBRID_EMPTY_STREAK_UNTIL_RESTART, normalizeResolvedFilename, primeMegaDebridUntilRestartForTests, recordMegaDebridEmptyResponseStreak, resetDebridLinkRuntimeStateForTests, resetMegaDebridRuntimeStateForTests } from "../src/main/debrid";
|
||||
import { clearMegaDebridEmptyResponseStreak, DebridService, extractRapidgatorFilenameFromHtml, fetchAllDebridHostInfo, fetchDebridLinkHostLimits, filenameFromRapidgatorUrlPath, getDebridLinkKeyRuntimeStateForTests, getMegaDebridAccountCooldownState, MEGA_DEBRID_EMPTY_STREAK_UNTIL_RESTART, normalizeResolvedFilename, primeMegaDebridLatencyForTests, primeMegaDebridUntilRestartForTests, recordMegaDebridEmptyResponseStreak, resetDebridLinkRuntimeStateForTests, resetMegaDebridRuntimeStateForTests } from "../src/main/debrid";
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
@@ -1463,6 +1463,84 @@ describe("debrid service", () => {
|
||||
]);
|
||||
}, 30000);
|
||||
|
||||
it("depriorisiert einen nachweislich langsamen Account in der Rotation (Single-Flight-Schutz)", async () => {
|
||||
const settings = {
|
||||
...defaultSettings(),
|
||||
token: "",
|
||||
bestToken: "",
|
||||
allDebridToken: "",
|
||||
megaLogin: "user1",
|
||||
megaPassword: "pass1",
|
||||
megaCredentials: "user1:pass1\nuser2:pass2",
|
||||
megaDebridPreferApi: false,
|
||||
providerOrder: [] as const,
|
||||
providerPrimary: "megadebrid" as const,
|
||||
providerSecondary: "none" as const,
|
||||
providerTertiary: "none" as const,
|
||||
autoProviderFallback: false
|
||||
};
|
||||
|
||||
globalThis.fetch = (async () => new Response("error", { status: 500 })) as typeof fetch;
|
||||
|
||||
const megaWeb = vi.fn(async () => ({
|
||||
fileName: "ok.rar",
|
||||
directUrl: "https://mega-web.example/ok.rar",
|
||||
fileSize: null,
|
||||
retriesUsed: 0
|
||||
}));
|
||||
|
||||
primeMegaDebridLatencyForTests(`${getMegaDebridAccountId("user1")}:web`, 15000);
|
||||
primeMegaDebridLatencyForTests(`${getMegaDebridAccountId("user2")}:web`, 800);
|
||||
|
||||
const service = new DebridService(settings, { megaWebUnrestrict: megaWeb });
|
||||
const usedIds: (string | undefined)[] = [];
|
||||
for (let i = 0; i < 2; i += 1) {
|
||||
const result = await service.unrestrictLink(`https://rapidgator.net/file/slow-${i}`);
|
||||
usedIds.push((result as { sourceAccountId?: string }).sourceAccountId);
|
||||
}
|
||||
|
||||
expect(usedIds).toEqual([
|
||||
getMegaDebridAccountId("user2"),
|
||||
getMegaDebridAccountId("user2")
|
||||
]);
|
||||
}, 30000);
|
||||
|
||||
it("nutzt den langsamen Account weiterhin, wenn die schnellen gesperrt sind (Failover-Reserve)", async () => {
|
||||
const settings = {
|
||||
...defaultSettings(),
|
||||
token: "",
|
||||
bestToken: "",
|
||||
allDebridToken: "",
|
||||
megaLogin: "user1",
|
||||
megaPassword: "pass1",
|
||||
megaCredentials: "user1:pass1\nuser2:pass2",
|
||||
megaDebridPreferApi: false,
|
||||
providerOrder: [] as const,
|
||||
providerPrimary: "megadebrid" as const,
|
||||
providerSecondary: "none" as const,
|
||||
providerTertiary: "none" as const,
|
||||
autoProviderFallback: false
|
||||
};
|
||||
|
||||
globalThis.fetch = (async () => new Response("error", { status: 500 })) as typeof fetch;
|
||||
|
||||
const megaWeb = vi.fn(async () => ({
|
||||
fileName: "ok.rar",
|
||||
directUrl: "https://mega-web.example/ok.rar",
|
||||
fileSize: null,
|
||||
retriesUsed: 0
|
||||
}));
|
||||
|
||||
primeMegaDebridLatencyForTests(`${getMegaDebridAccountId("user1")}:web`, 15000);
|
||||
primeMegaDebridLatencyForTests(`${getMegaDebridAccountId("user2")}:web`, 800);
|
||||
primeMegaDebridUntilRestartForTests(`${getMegaDebridAccountId("user2")}:web`);
|
||||
|
||||
const service = new DebridService(settings, { megaWebUnrestrict: megaWeb });
|
||||
const result = await service.unrestrictLink("https://rapidgator.net/file/slow-fallback");
|
||||
|
||||
expect((result as { sourceAccountId?: string }).sourceAccountId).toBe(getMegaDebridAccountId("user1"));
|
||||
}, 30000);
|
||||
|
||||
it("rotates to the next Mega-Debrid account when one hits its daily limit (error-based)", async () => {
|
||||
const settings = {
|
||||
...defaultSettings(),
|
||||
|
||||
Reference in New Issue
Block a user