Release v1.4.16 with crash prevention and hang protection

- Add 30s fetch timeouts to ALL API calls (Real-Debrid, BestDebrid, AllDebrid, Mega-Web)
- Fix race condition in concurrent worker indexing (runWithConcurrency)
- Guard JSON.parse in RealDebrid response with try-catch
- Add try-catch to fs.mkdirSync in download pipeline (handles permission denied)
- Convert MD5/SHA1 hashing to streaming (prevents OOM on large files)
- Add error handling for hash manifest file reading
- Prevent infinite hangs on unresponsive API endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe
2026-02-27 21:43:40 +01:00
co-authored by Claude Opus 4.6
parent 147269849d
commit ea6301d326
7 changed files with 58 additions and 21 deletions
+12 -4
View File
@@ -50,7 +50,12 @@ export function readHashManifest(packageDir: string): Map<string, ParsedHashEntr
continue;
}
const filePath = path.join(packageDir, entry.name);
const lines = fs.readFileSync(filePath, "utf8").split(/\r?\n/);
let lines: string[];
try {
lines = fs.readFileSync(filePath, "utf8").split(/\r?\n/);
} catch {
continue;
}
for (const line of lines) {
const parsed = parseHashLine(line);
if (!parsed) {
@@ -93,9 +98,12 @@ async function hashFile(filePath: string, algorithm: "crc32" | "md5" | "sha1"):
}
const hash = crypto.createHash(algorithm);
const data = fs.readFileSync(filePath);
hash.update(data);
return hash.digest("hex").toLowerCase();
const stream = fs.createReadStream(filePath, { highWaterMark: 1024 * 1024 });
return await new Promise<string>((resolve, reject) => {
stream.on("data", (chunk: string | Buffer) => hash.update(typeof chunk === "string" ? Buffer.from(chunk) : chunk));
stream.on("error", reject);
stream.on("end", () => resolve(hash.digest("hex").toLowerCase()));
});
}
export async function validateFileAgainstManifest(filePath: string, packageDir: string): Promise<{ ok: boolean; message: string }> {