Mirror extractor logs to item logs
This commit is contained in:
parent
9449788e56
commit
c898c6de65
@ -1159,6 +1159,26 @@ export function resolveArchiveItemsFromList(archiveName: string, items: Download
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractArchiveNameFromExtractorLogMessage(message: string): string | null {
|
||||||
|
const text = String(message || "").trim();
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const patterns = [
|
||||||
|
/archive=([^,\s|]+)/i,
|
||||||
|
/Entpacke Archiv:\s*([^\s]+)\s*->/i,
|
||||||
|
/Entpack-Fehler\s+([^\s]+)\s+\[/i
|
||||||
|
];
|
||||||
|
for (const pattern of patterns) {
|
||||||
|
const match = text.match(pattern);
|
||||||
|
if (match?.[1]) {
|
||||||
|
return match[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function retryDelayWithJitter(attempt: number, baseMs: number): number {
|
function retryDelayWithJitter(attempt: number, baseMs: number): number {
|
||||||
const exponential = baseMs * Math.pow(1.5, Math.min(attempt - 1, 14));
|
const exponential = baseMs * Math.pow(1.5, Math.min(attempt - 1, 14));
|
||||||
const capped = Math.min(exponential, 120000);
|
const capped = Math.min(exponential, 120000);
|
||||||
@ -1368,6 +1388,25 @@ export class DownloadManager extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private logExtractionForItems(
|
||||||
|
pkg: PackageEntry,
|
||||||
|
items: DownloadItem[],
|
||||||
|
prefix: string,
|
||||||
|
level: "INFO" | "WARN" | "ERROR",
|
||||||
|
message: string
|
||||||
|
): void {
|
||||||
|
const fullMessage = `${prefix}: ${message}`;
|
||||||
|
this.logPackageForPackage(pkg, level, fullMessage);
|
||||||
|
|
||||||
|
const archiveName = extractArchiveNameFromExtractorLogMessage(message);
|
||||||
|
if (!archiveName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const item of resolveArchiveItemsFromList(archiveName, items)) {
|
||||||
|
this.logPackageForItem(item, level, fullMessage, { archiveName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private logPackageForItem(
|
private logPackageForItem(
|
||||||
item: DownloadItem,
|
item: DownloadItem,
|
||||||
level: "INFO" | "WARN" | "ERROR",
|
level: "INFO" | "WARN" | "ERROR",
|
||||||
@ -8714,7 +8753,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
hybridMode: true,
|
hybridMode: true,
|
||||||
maxParallel: this.settings.maxParallelExtract || 2,
|
maxParallel: this.settings.maxParallelExtract || 2,
|
||||||
extractCpuPriority: "high",
|
extractCpuPriority: "high",
|
||||||
onLog: (level, message) => this.logPackageForPackage(pkg, level, `Hybrid-Extractor: ${message}`),
|
onLog: (level, message) => this.logExtractionForItems(pkg, items, "Hybrid-Extractor", level, message),
|
||||||
onArchiveFailure: (failure) => {
|
onArchiveFailure: (failure) => {
|
||||||
const failedArchiveKey = readyArchiveKeyByName.get(String(failure.archiveName || "").toLowerCase());
|
const failedArchiveKey = readyArchiveKeyByName.get(String(failure.archiveName || "").toLowerCase());
|
||||||
if (failedArchiveKey) {
|
if (failedArchiveKey) {
|
||||||
@ -9193,7 +9232,7 @@ export class DownloadManager extends EventEmitter {
|
|||||||
// All downloads finished — use NORMAL OS priority so extraction runs at
|
// All downloads finished — use NORMAL OS priority so extraction runs at
|
||||||
// full speed (matching manual 7-Zip/WinRAR speed).
|
// full speed (matching manual 7-Zip/WinRAR speed).
|
||||||
extractCpuPriority: "high",
|
extractCpuPriority: "high",
|
||||||
onLog: (level, message) => this.logPackageForPackage(pkg, level, `Extractor: ${message}`),
|
onLog: (level, message) => this.logExtractionForItems(pkg, completedItems, "Extractor", level, message),
|
||||||
onArchiveFailure: (failure) => {
|
onArchiveFailure: (failure) => {
|
||||||
if (autoRecoveredArchives.has(failure.archiveName)) {
|
if (autoRecoveredArchives.has(failure.archiveName)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import http from "node:http";
|
|||||||
import { EventEmitter, once } from "node:events";
|
import { EventEmitter, once } from "node:events";
|
||||||
import AdmZip from "adm-zip";
|
import AdmZip from "adm-zip";
|
||||||
import { afterEach, describe, expect, it } from "vitest";
|
import { afterEach, describe, expect, it } from "vitest";
|
||||||
import { DownloadManager, getAuthoritativeRealDebridTotal } from "../src/main/download-manager";
|
import { DownloadManager, extractArchiveNameFromExtractorLogMessage, getAuthoritativeRealDebridTotal } from "../src/main/download-manager";
|
||||||
import { defaultSettings } from "../src/main/constants";
|
import { defaultSettings } from "../src/main/constants";
|
||||||
import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys";
|
import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys";
|
||||||
import { getProviderUsageDayKey } from "../src/shared/provider-daily-limits";
|
import { getProviderUsageDayKey } from "../src/shared/provider-daily-limits";
|
||||||
@ -15,6 +15,18 @@ import { primeDebridLinkRuntimeCooldownForTests, resetDebridLinkRuntimeStateForT
|
|||||||
const tempDirs: string[] = [];
|
const tempDirs: string[] = [];
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
|
|
||||||
|
describe("extractArchiveNameFromExtractorLogMessage", () => {
|
||||||
|
it("detects archive names from extractor log variants", () => {
|
||||||
|
expect(extractArchiveNameFromExtractorLogMessage("Extract-Backend Start: archive=scn-dhanbs7-S02E008.rar, mode=legacy")).toBe("scn-dhanbs7-S02E008.rar");
|
||||||
|
expect(extractArchiveNameFromExtractorLogMessage("Entpacke Archiv: scn-dhanbs7-S02E008.rar -> C:\\target")).toBe("scn-dhanbs7-S02E008.rar");
|
||||||
|
expect(extractArchiveNameFromExtractorLogMessage("Entpack-Fehler scn-dhanbs7-S02E008.rar [missing_parts]: Error: boom")).toBe("scn-dhanbs7-S02E008.rar");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns null when no archive name is present", () => {
|
||||||
|
expect(extractArchiveNameFromExtractorLogMessage("Post-Processing Entpacken Ende")).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
async function waitFor(predicate: () => boolean, timeoutMs = 15000): Promise<void> {
|
async function waitFor(predicate: () => boolean, timeoutMs = 15000): Promise<void> {
|
||||||
const started = Date.now();
|
const started = Date.now();
|
||||||
while (!predicate()) {
|
while (!predicate()) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user