Compare commits

..

No commits in common. "afef8dae6f05feaa3cca16b7b9acfefbf0b058f8" and "7d09479b44066dc2b659b7a18e4f021da34648c3" have entirely different histories.

2 changed files with 13 additions and 29 deletions

View File

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

View File

@ -6926,38 +6926,33 @@ export class DownloadManager extends EventEmitter {
continue; continue;
} }
// Disk-fallback: if all parts exist on disk at their full expected size but some // Disk-fallback: if all parts exist on disk but some items lack "completed" status,
// items lack "completed" status, allow extraction. This handles items that finished // allow extraction if none of those parts are actively downloading/validating.
// downloading but whose status was not updated (crash between write and persist). // This handles items that finished downloading but whose status was not updated.
const missingParts = partsOnDisk.filter((part) => !completedPaths.has(pathKey(part))); const missingParts = partsOnDisk.filter((part) => !completedPaths.has(pathKey(part)));
let allMissingFullOnDisk = true; let allMissingExistOnDisk = true;
for (const part of missingParts) { for (const part of missingParts) {
try { try {
const stat = await fs.promises.stat(part); const stat = await fs.promises.stat(part);
// Find the item that owns this file to get its expected totalBytes if (stat.size < 10240) {
const ownerItem = this.findItemByDiskPath(pkg, part); allMissingExistOnDisk = false;
const minBytes = ownerItem?.totalBytes && ownerItem.totalBytes > 0
? ownerItem.totalBytes - ALLOCATION_UNIT_SIZE
: 10240;
if (stat.size < minBytes) {
allMissingFullOnDisk = false;
break; break;
} }
} catch { } catch {
allMissingFullOnDisk = false; allMissingExistOnDisk = false;
break; break;
} }
} }
if (!allMissingFullOnDisk) { if (!allMissingExistOnDisk) {
continue; continue;
} }
// Any non-completed item blocks extraction — failed/cancelled/stopped items may // Any non-completed item blocks extraction — cancelled/stopped items may
// have partial files on disk that would corrupt the extraction. // have partial files on disk that would corrupt the extraction.
const anyNonCompletedItem = missingParts.some((part) => { const anyActivelyProcessing = missingParts.some((part) => {
const status = pendingItemStatus.get(pathKey(part)); const status = pendingItemStatus.get(pathKey(part));
return status !== undefined; return status !== undefined && status !== "failed";
}); });
if (anyNonCompletedItem) { if (anyActivelyProcessing) {
continue; continue;
} }
// Safety: if any pending item in the package has neither targetPath nor fileName, // Safety: if any pending item in the package has neither targetPath nor fileName,
@ -6980,17 +6975,6 @@ export class DownloadManager extends EventEmitter {
return ready; return ready;
} }
private findItemByDiskPath(pkg: PackageEntry, diskPath: string): DownloadItem | undefined {
const key = pathKey(diskPath);
for (const itemId of pkg.itemIds) {
const item = this.session.items[itemId];
if (!item) continue;
if (item.targetPath && pathKey(item.targetPath) === key) return item;
if (item.fileName && pkg.outputDir && pathKey(path.join(pkg.outputDir, item.fileName)) === key) return item;
}
return undefined;
}
private looksLikeArchivePart(fileName: string, entryPointName: string): boolean { private looksLikeArchivePart(fileName: string, entryPointName: string): boolean {
const multipartMatch = entryPointName.match(/^(.*)\.part0*1\.rar$/i); const multipartMatch = entryPointName.match(/^(.*)\.part0*1\.rar$/i);
if (multipartMatch) { if (multipartMatch) {