Fix pause bugs, faster stall retry

- Pause now aborts active extractions (previously extraction continued
  during pause, showing wrong status like Provider-Cooldown)
- Unpause clears provider circuit breaker for fresh start
- Post-processing status checks account for global pause state
- Reduce stall detection timeout from 30s to 15s for faster retry
- Reduce stall retry base delay from 500ms to 300ms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-02 21:15:00 +01:00
parent 55e5b0079a
commit ba7fe24a0a
2 changed files with 15 additions and 8 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.5.20", "version": "1.5.21",
"description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)",
"main": "build/main/main/main.js", "main": "build/main/main/main.js",
"author": "Sucukdeluxe", "author": "Sucukdeluxe",

View File

@ -39,7 +39,7 @@ type ActiveTask = {
unrestrictRetries?: number; unrestrictRetries?: number;
}; };
const DEFAULT_DOWNLOAD_STALL_TIMEOUT_MS = 30000; const DEFAULT_DOWNLOAD_STALL_TIMEOUT_MS = 15000;
const DEFAULT_DOWNLOAD_CONNECT_TIMEOUT_MS = 25000; const DEFAULT_DOWNLOAD_CONNECT_TIMEOUT_MS = 25000;
@ -2463,10 +2463,17 @@ export class DownloadManager extends EventEmitter {
const wasPaused = this.session.paused; const wasPaused = this.session.paused;
this.session.paused = !this.session.paused; this.session.paused = !this.session.paused;
// When pausing: abort active extractions so they don't continue during pause
if (!wasPaused && this.session.paused) {
this.abortPostProcessing("pause");
}
// When unpausing: clear all retry delays so stuck queued items restart immediately, // When unpausing: clear all retry delays so stuck queued items restart immediately,
// and abort long-stuck validating/downloading tasks so they get retried fresh. // and abort long-stuck validating/downloading tasks so they get retried fresh.
if (wasPaused && !this.session.paused) { if (wasPaused && !this.session.paused) {
this.retryAfterByItem.clear(); this.retryAfterByItem.clear();
// Reset provider circuit breaker so items don't sit in cooldown after unpause
this.providerFailures.clear();
const now = nowMs(); const now = nowMs();
for (const active of this.activeTasks.values()) { for (const active of this.activeTasks.values()) {
@ -2814,7 +2821,7 @@ export class DownloadManager extends EventEmitter {
} }
if (pkg.status === "extracting" || pkg.status === "integrity_check") { if (pkg.status === "extracting" || pkg.status === "integrity_check") {
pkg.status = pkg.enabled ? "queued" : "paused"; pkg.status = (pkg.enabled && !this.session.paused) ? "queued" : "paused";
pkg.updatedAt = nowMs(); pkg.updatedAt = nowMs();
} }
@ -3790,7 +3797,7 @@ export class DownloadManager extends EventEmitter {
item.totalBytes = null; item.totalBytes = null;
this.dropItemContribution(item.id); this.dropItemContribution(item.id);
} }
let stallDelayMs = retryDelayWithJitter(active.stallRetries, 500); let stallDelayMs = retryDelayWithJitter(active.stallRetries, 300);
// Respect provider cooldown // Respect provider cooldown
if (item.provider) { if (item.provider) {
const providerCooldown = this.getProviderCooldownRemaining(item.provider); const providerCooldown = this.getProviderCooldownRemaining(item.provider);
@ -5103,18 +5110,18 @@ export class DownloadManager extends EventEmitter {
if (!allDone && this.settings.hybridExtract && this.settings.autoExtract && failed === 0 && success > 0) { if (!allDone && this.settings.hybridExtract && this.settings.autoExtract && failed === 0 && success > 0) {
await this.runHybridExtraction(packageId, pkg, items, signal); await this.runHybridExtraction(packageId, pkg, items, signal);
if (signal?.aborted) { if (signal?.aborted) {
pkg.status = pkg.enabled ? "queued" : "paused"; pkg.status = (pkg.enabled && !this.session.paused) ? "queued" : "paused";
pkg.updatedAt = nowMs(); pkg.updatedAt = nowMs();
return; return;
} }
pkg.status = pkg.enabled ? "downloading" : "paused"; pkg.status = (pkg.enabled && !this.session.paused) ? "downloading" : "paused";
pkg.updatedAt = nowMs(); pkg.updatedAt = nowMs();
this.emitState(); this.emitState();
return; return;
} }
if (!allDone) { if (!allDone) {
pkg.status = pkg.enabled ? "downloading" : "paused"; pkg.status = (pkg.enabled && !this.session.paused) ? "downloading" : "paused";
logger.info(`Post-Processing verschoben: pkg=${pkg.name}, noch offene items`); logger.info(`Post-Processing verschoben: pkg=${pkg.name}, noch offene items`);
return; return;
} }
@ -5291,7 +5298,7 @@ export class DownloadManager extends EventEmitter {
} }
entry.updatedAt = nowMs(); entry.updatedAt = nowMs();
} }
pkg.status = pkg.enabled ? "queued" : "paused"; pkg.status = (pkg.enabled && !this.session.paused) ? "queued" : "paused";
pkg.updatedAt = nowMs(); pkg.updatedAt = nowMs();
logger.info(`Post-Processing Entpacken abgebrochen: pkg=${pkg.name}`); logger.info(`Post-Processing Entpacken abgebrochen: pkg=${pkg.name}`);
return; return;