Compare commits
No commits in common. "56aaf99464a7d83a3408c1f3837789b80be4f884" and "d8535990ae4068e11fde4ad286c1f4e7d9e6f5ba" have entirely different histories.
56aaf99464
...
d8535990ae
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "real-debrid-downloader",
|
"name": "real-debrid-downloader",
|
||||||
"version": "1.7.98",
|
"version": "1.7.97",
|
||||||
"description": "Desktop downloader",
|
"description": "Desktop downloader",
|
||||||
"main": "build/main/main/main.js",
|
"main": "build/main/main/main.js",
|
||||||
"author": "Sucukdeluxe",
|
"author": "Sucukdeluxe",
|
||||||
|
|||||||
@ -651,23 +651,6 @@ export function classifyExtractionError(errorText: string): ExtractErrorCategory
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shouldSerialRetryParallelFailures(
|
|
||||||
extractedCount: number,
|
|
||||||
failedCategories: ExtractErrorCategory[]
|
|
||||||
): boolean {
|
|
||||||
if (failedCategories.length === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (extractedCount > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return failedCategories.every((category) =>
|
|
||||||
category === "crc_error"
|
|
||||||
|| category === "wrong_password"
|
|
||||||
|| category === "unknown"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function shouldFallbackLegacyRarToJvm(
|
export function shouldFallbackLegacyRarToJvm(
|
||||||
archivePath: string,
|
archivePath: string,
|
||||||
configuredMode: ExtractBackendMode,
|
configuredMode: ExtractBackendMode,
|
||||||
@ -3018,7 +3001,6 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
let learnedPassword = cachedPackagePassword;
|
let learnedPassword = cachedPackagePassword;
|
||||||
let packageNeedsFlatMode = false;
|
let packageNeedsFlatMode = false;
|
||||||
const extractedArchives = new Set<string>();
|
const extractedArchives = new Set<string>();
|
||||||
const failedArchiveCategories = new Map<string, ExtractErrorCategory>();
|
|
||||||
for (const archivePath of candidates) {
|
for (const archivePath of candidates) {
|
||||||
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
if (resumeCompleted.has(archiveNameKey(path.basename(archivePath)))) {
|
||||||
extractedArchives.add(archivePath);
|
extractedArchives.add(archivePath);
|
||||||
@ -3219,7 +3201,6 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
}
|
}
|
||||||
extracted += 1;
|
extracted += 1;
|
||||||
extractedArchives.add(archivePath);
|
extractedArchives.add(archivePath);
|
||||||
failedArchiveCategories.delete(archivePath);
|
|
||||||
resumeCompleted.add(archiveResumeKey);
|
resumeCompleted.add(archiveResumeKey);
|
||||||
await writeExtractResumeState(options.packageDir, resumeCompleted, options.packageId);
|
await writeExtractResumeState(options.packageDir, resumeCompleted, options.packageId);
|
||||||
logger.info(`Entpacken erfolgreich: ${path.basename(archivePath)}`);
|
logger.info(`Entpacken erfolgreich: ${path.basename(archivePath)}`);
|
||||||
@ -3243,7 +3224,6 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
failed += 1;
|
failed += 1;
|
||||||
lastError = errorText;
|
lastError = errorText;
|
||||||
const errorCategory = classifyExtractionError(errorText);
|
const errorCategory = classifyExtractionError(errorText);
|
||||||
failedArchiveCategories.set(archivePath, errorCategory);
|
|
||||||
const hintedError = error as ExtractionErrorWithHints;
|
const hintedError = error as ExtractionErrorWithHints;
|
||||||
options.onArchiveFailure?.({
|
options.onArchiveFailure?.({
|
||||||
archiveName,
|
archiveName,
|
||||||
@ -3349,33 +3329,6 @@ export async function extractPackageArchives(options: ExtractOptions): Promise<{
|
|||||||
|
|
||||||
if (abortError) throw new Error("aborted:extract");
|
if (abortError) throw new Error("aborted:extract");
|
||||||
|
|
||||||
if (failed > 0 && extracted === 0) {
|
|
||||||
const failedArchives = parallelQueue.filter((ap) => !extractedArchives.has(ap) && !resumeCompleted.has(archiveNameKey(path.basename(ap))));
|
|
||||||
const failedCategories = failedArchives.map((archivePath) => failedArchiveCategories.get(archivePath) || "unknown");
|
|
||||||
if (failedArchives.length > 0 && shouldSerialRetryParallelFailures(extracted, failedCategories)) {
|
|
||||||
const categorySummary = [...new Set(failedCategories)].join(",");
|
|
||||||
logger.info(
|
|
||||||
`Serielle Wiederholung nach Parallel-Fehlstart: ${failedArchives.length} Archive werden einzeln wiederholt ` +
|
|
||||||
`(categories=${categorySummary || "unknown"})`
|
|
||||||
);
|
|
||||||
let retryRecovered = 0;
|
|
||||||
for (const archivePath of failedArchives) {
|
|
||||||
if (options.signal?.aborted || noExtractorEncountered) break;
|
|
||||||
try {
|
|
||||||
failed -= 1;
|
|
||||||
await extractSingleArchive(archivePath);
|
|
||||||
retryRecovered += 1;
|
|
||||||
} catch (retryError) {
|
|
||||||
const errText = String(retryError);
|
|
||||||
if (isExtractAbortError(errText)) throw retryError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (retryRecovered > 0) {
|
|
||||||
logger.info(`Serielle Wiederholung nach Parallel-Fehlstart: ${retryRecovered}/${failedArchives.length} Archive erfolgreich entpackt`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Retry failed wrong_password archives serially ──
|
// ── Retry failed wrong_password archives serially ──
|
||||||
// Parallel UnRAR processes writing to the same target directory can cause
|
// Parallel UnRAR processes writing to the same target directory can cause
|
||||||
// CRC mismatches that are misreported as "Incorrect password".
|
// CRC mismatches that are misreported as "Incorrect password".
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import {
|
|||||||
archiveFilenamePasswords,
|
archiveFilenamePasswords,
|
||||||
detectArchiveSignature,
|
detectArchiveSignature,
|
||||||
classifyExtractionError,
|
classifyExtractionError,
|
||||||
shouldSerialRetryParallelFailures,
|
|
||||||
findArchiveCandidates,
|
findArchiveCandidates,
|
||||||
orderExtractorCandidatesForArchive,
|
orderExtractorCandidatesForArchive,
|
||||||
resolveExtractorBackendModeForArchive,
|
resolveExtractorBackendModeForArchive,
|
||||||
@ -1049,19 +1048,6 @@ describe("extractor", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("shouldSerialRetryParallelFailures", () => {
|
|
||||||
it("keeps serial recovery enabled after mixed parallel results", () => {
|
|
||||||
expect(shouldSerialRetryParallelFailures(1, ["wrong_password"])).toBe(true);
|
|
||||||
expect(shouldSerialRetryParallelFailures(2, ["missing_parts"])).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("only retries a total parallel wipe-out for contention-like failures", () => {
|
|
||||||
expect(shouldSerialRetryParallelFailures(0, ["crc_error", "wrong_password", "unknown"])).toBe(true);
|
|
||||||
expect(shouldSerialRetryParallelFailures(0, ["missing_parts"])).toBe(false);
|
|
||||||
expect(shouldSerialRetryParallelFailures(0, ["unsupported_format", "crc_error"])).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("password discovery", () => {
|
describe("password discovery", () => {
|
||||||
it("reports per-archive failures through onArchiveFailure", async () => {
|
it("reports per-archive failures through onArchiveFailure", async () => {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-extract-failure-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-extract-failure-"));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user