Compare commits

..

No commits in common. "e3b4a4ba19184e006057ff8a8ea915f1f2014b4c" and "1cda391dfe86fd66d0df96730cbd58f99e4eabb1" have entirely different histories.

3 changed files with 29 additions and 38 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.6.52", "version": "1.6.50",
"description": "Desktop downloader", "description": "Desktop downloader",
"main": "build/main/main/main.js", "main": "build/main/main/main.js",
"author": "Sucukdeluxe", "author": "Sucukdeluxe",

View File

@ -1384,10 +1384,6 @@ export class DownloadManager extends EventEmitter {
addedPackages += 1; addedPackages += 1;
} }
if (addedPackages > 0 || addedLinks > 0) {
const pkgNames = packages.filter((p) => p.links.length > 0).map((p) => p.name).join(", ");
logger.info(`Pakete hinzugefügt: ${addedPackages} Paket(e), ${addedLinks} Link(s) [${pkgNames}]`);
}
this.persistSoon(); this.persistSoon();
this.emitState(); this.emitState();
if (unresolvedByLink.size > 0) { if (unresolvedByLink.size > 0) {
@ -4740,7 +4736,6 @@ export class DownloadManager extends EventEmitter {
item.fullStatus = `Starte... (${unrestricted.providerLabel})`; item.fullStatus = `Starte... (${unrestricted.providerLabel})`;
item.updatedAt = nowMs(); item.updatedAt = nowMs();
this.emitState(); this.emitState();
logger.info(`Download Start: ${item.fileName} (${humanSize(unrestricted.fileSize || 0)}) via ${unrestricted.providerLabel}, pkg=${pkg.name}`);
const maxAttempts = maxItemAttempts; const maxAttempts = maxItemAttempts;
let done = false; let done = false;
@ -6366,11 +6361,9 @@ export class DownloadManager extends EventEmitter {
const resolveArchiveItems = (archiveName: string): DownloadItem[] => const resolveArchiveItems = (archiveName: string): DownloadItem[] =>
resolveArchiveItemsFromList(archiveName, items); resolveArchiveItemsFromList(archiveName, items);
// Track multiple active archives for parallel hybrid extraction. // Track multiple active archives for parallel hybrid extraction
// Using plain object instead of Map — Map.has() was mysteriously const activeHybridArchiveMap = new Map<string, DownloadItem[]>();
// returning false despite Map.set() being called with the same key. const hybridArchiveStartTimes = new Map<string, number>();
const resolvedItemsCache: Record<string, DownloadItem[]> = Object.create(null);
const archiveStartTimesCache: Record<string, number> = Object.create(null);
let hybridLastEmitAt = 0; let hybridLastEmitAt = 0;
// Mark items based on whether their archive is actually ready for extraction. // Mark items based on whether their archive is actually ready for extraction.
@ -6419,18 +6412,18 @@ export class DownloadManager extends EventEmitter {
if (progress.phase === "done") { if (progress.phase === "done") {
// Do NOT mark remaining archives as "Done" here — some may have // Do NOT mark remaining archives as "Done" here — some may have
// failed. The post-extraction code (result.failed check) will // failed. The post-extraction code (result.failed check) will
// assign the correct label. Only clear the tracking caches. // assign the correct label. Only clear the tracking maps.
for (const key of Object.keys(resolvedItemsCache)) delete resolvedItemsCache[key]; activeHybridArchiveMap.clear();
for (const key of Object.keys(archiveStartTimesCache)) delete archiveStartTimesCache[key]; hybridArchiveStartTimes.clear();
return; return;
} }
if (progress.archiveName) { if (progress.archiveName) {
// Resolve items for this archive if not yet tracked // Resolve items for this archive if not yet tracked
if (!(progress.archiveName in resolvedItemsCache)) { if (!activeHybridArchiveMap.has(progress.archiveName)) {
const resolved = resolveArchiveItems(progress.archiveName); const resolved = resolveArchiveItems(progress.archiveName);
resolvedItemsCache[progress.archiveName] = resolved; activeHybridArchiveMap.set(progress.archiveName, resolved);
archiveStartTimesCache[progress.archiveName] = nowMs(); hybridArchiveStartTimes.set(progress.archiveName, nowMs());
if (resolved.length === 0) { if (resolved.length === 0) {
logger.warn(`resolveArchiveItems (hybrid): KEINE Items gefunden für archiveName="${progress.archiveName}", items.length=${items.length}, itemNames=[${items.slice(0, 5).map((i) => path.basename(i.targetPath || i.fileName || "?")).join(", ")}]`); logger.warn(`resolveArchiveItems (hybrid): KEINE Items gefunden für archiveName="${progress.archiveName}", items.length=${items.length}, itemNames=[${items.slice(0, 5).map((i) => path.basename(i.targetPath || i.fileName || "?")).join(", ")}]`);
} else { } else {
@ -6449,12 +6442,12 @@ export class DownloadManager extends EventEmitter {
this.emitState(true); this.emitState(true);
} }
} }
const archItems = resolvedItemsCache[progress.archiveName] || []; const archItems = activeHybridArchiveMap.get(progress.archiveName)!;
// If archive is at 100%, mark its items as done and remove from active // If archive is at 100%, mark its items as done and remove from active
if (Number(progress.archivePercent ?? 0) >= 100) { if (Number(progress.archivePercent ?? 0) >= 100) {
const doneAt = nowMs(); const doneAt = nowMs();
const startedAt = archiveStartTimesCache[progress.archiveName] || doneAt; const startedAt = hybridArchiveStartTimes.get(progress.archiveName) || doneAt;
const doneLabel = formatExtractDone(doneAt - startedAt); const doneLabel = formatExtractDone(doneAt - startedAt);
for (const entry of archItems) { for (const entry of archItems) {
if (!isExtractedLabel(entry.fullStatus)) { if (!isExtractedLabel(entry.fullStatus)) {
@ -6462,8 +6455,8 @@ export class DownloadManager extends EventEmitter {
entry.updatedAt = doneAt; entry.updatedAt = doneAt;
} }
} }
delete resolvedItemsCache[progress.archiveName]; activeHybridArchiveMap.delete(progress.archiveName);
delete archiveStartTimesCache[progress.archiveName]; hybridArchiveStartTimes.delete(progress.archiveName);
// Show transitional label while next archive initializes // Show transitional label while next archive initializes
const done = progress.current + 1; const done = progress.current + 1;
if (done < progress.total) { if (done < progress.total) {
@ -6755,10 +6748,9 @@ export class DownloadManager extends EventEmitter {
} }
}, extractTimeoutMs); }, extractTimeoutMs);
try { try {
// Track multiple active archives for parallel extraction. // Track multiple active archives for parallel extraction
// Using plain object — Map.has() had a mysterious caching failure. const activeArchiveItemsMap = new Map<string, DownloadItem[]>();
const fullResolvedCache: Record<string, DownloadItem[]> = Object.create(null); const archiveStartTimes = new Map<string, number>();
const fullStartTimesCache: Record<string, number> = Object.create(null);
const result = await extractPackageArchives({ const result = await extractPackageArchives({
packageDir: pkg.outputDir, packageDir: pkg.outputDir,
@ -6784,19 +6776,19 @@ export class DownloadManager extends EventEmitter {
if (progress.phase === "done") { if (progress.phase === "done") {
// Do NOT mark remaining archives as "Done" here — some may have // Do NOT mark remaining archives as "Done" here — some may have
// failed. The post-extraction code (result.failed check) will // failed. The post-extraction code (result.failed check) will
// assign the correct label. Only clear the tracking caches. // assign the correct label. Only clear the tracking maps.
for (const key of Object.keys(fullResolvedCache)) delete fullResolvedCache[key]; activeArchiveItemsMap.clear();
for (const key of Object.keys(fullStartTimesCache)) delete fullStartTimesCache[key]; archiveStartTimes.clear();
emitExtractStatus("Entpacken 100%", true); emitExtractStatus("Entpacken 100%", true);
return; return;
} }
if (progress.archiveName) { if (progress.archiveName) {
// Resolve items for this archive if not yet tracked // Resolve items for this archive if not yet tracked
if (!(progress.archiveName in fullResolvedCache)) { if (!activeArchiveItemsMap.has(progress.archiveName)) {
const resolved = resolveArchiveItems(progress.archiveName); const resolved = resolveArchiveItems(progress.archiveName);
fullResolvedCache[progress.archiveName] = resolved; activeArchiveItemsMap.set(progress.archiveName, resolved);
fullStartTimesCache[progress.archiveName] = nowMs(); archiveStartTimes.set(progress.archiveName, nowMs());
if (resolved.length === 0) { if (resolved.length === 0) {
logger.warn(`resolveArchiveItems (full): KEINE Items für archiveName="${progress.archiveName}", completedItems=${completedItems.length}, names=[${completedItems.slice(0, 5).map((i) => path.basename(i.targetPath || i.fileName || "?")).join(", ")}]`); logger.warn(`resolveArchiveItems (full): KEINE Items für archiveName="${progress.archiveName}", completedItems=${completedItems.length}, names=[${completedItems.slice(0, 5).map((i) => path.basename(i.targetPath || i.fileName || "?")).join(", ")}]`);
} else { } else {
@ -6813,12 +6805,12 @@ export class DownloadManager extends EventEmitter {
emitExtractStatus(`Entpacken ${progress.percent}% · ${progress.archiveName}`, true); emitExtractStatus(`Entpacken ${progress.percent}% · ${progress.archiveName}`, true);
} }
} }
const archiveItems = fullResolvedCache[progress.archiveName] || []; const archiveItems = activeArchiveItemsMap.get(progress.archiveName)!;
// If archive is at 100%, mark its items as done and remove from active // If archive is at 100%, mark its items as done and remove from active
if (Number(progress.archivePercent ?? 0) >= 100) { if (Number(progress.archivePercent ?? 0) >= 100) {
const doneAt = nowMs(); const doneAt = nowMs();
const startedAt = fullStartTimesCache[progress.archiveName] || doneAt; const startedAt = archiveStartTimes.get(progress.archiveName) || doneAt;
const doneLabel = formatExtractDone(doneAt - startedAt); const doneLabel = formatExtractDone(doneAt - startedAt);
for (const entry of archiveItems) { for (const entry of archiveItems) {
if (!isExtractedLabel(entry.fullStatus)) { if (!isExtractedLabel(entry.fullStatus)) {
@ -6826,8 +6818,8 @@ export class DownloadManager extends EventEmitter {
entry.updatedAt = doneAt; entry.updatedAt = doneAt;
} }
} }
delete fullResolvedCache[progress.archiveName]; activeArchiveItemsMap.delete(progress.archiveName);
delete fullStartTimesCache[progress.archiveName]; archiveStartTimes.delete(progress.archiveName);
// Show transitional label while next archive initializes // Show transitional label while next archive initializes
const done = progress.current + 1; const done = progress.current + 1;
if (done < progress.total) { if (done < progress.total) {

View File

@ -1019,9 +1019,8 @@ function runJvmExtractCommand(
const args = [ const args = [
"-Dfile.encoding=UTF-8", "-Dfile.encoding=UTF-8",
`-Djava.io.tmpdir=${jvmTmpDir}`, `-Djava.io.tmpdir=${jvmTmpDir}`,
"-Xms64m", "-Xms32m",
"-Xmx1g", "-Xmx512m",
"-XX:+UseSerialGC",
"-cp", "-cp",
layout.classPath, layout.classPath,
JVM_EXTRACTOR_MAIN_CLASS, JVM_EXTRACTOR_MAIN_CLASS,