-
v2.0.0-beta.5 Stable
released this
2026-03-08 19:39:07 +01:00 | 0 commits to main since this releasev2.0.0-beta.5
-
v2.0.0-beta.4 Stable
released this
2026-03-08 19:19:32 +01:00 | 2 commits to main since this releasev2.0.0-beta.4 — Fix Auto-Updater
Bugfix
- Auto-updater pointed to stable repo instead of beta repo —
DEFAULT_UPDATE_REPOinconstants.tswas still set toAdministrator/real-debrid-downloader(the stable release repo). The beta app checked for updates there, found no newer version than what's in stable, and reported "Kein Update verfügbar". Changed toAdministrator/beta-real-debrid-downloaderso the beta app discovers its own releases.
Note
Since v2.0.0-beta.2 and beta.3 had the wrong update repo, you need to manually download and install beta.4 from this release page. After that, auto-updates will work correctly for future beta releases.
- Auto-updater pointed to stable repo instead of beta repo —
-
v2.0.0-beta.3 Stable
released this
2026-03-08 19:16:38 +01:00 | 4 commits to main since this releasev2.0.0-beta.3 — Fix "Delete Selected" Not Working
Bugfix
-
cancelPackage did not remove packages from session — The new v2
cancelPackage()only marked packages and items as "cancelled" (status change) but never actually removed them fromsession.packages,session.items, orsession.packageOrder. The old download-manager calledremovePackageFromSession()which deletes all entries. This caused "Ausgewählte löschen" (Delete Selected) to appear to do nothing — packages stayed visible in the UI despite being cancelled.Fixed by rewriting
cancelPackage()to:- Abort all active downloads for the package
- Record run outcomes for non-completed items
- Remove all items from
session.itemsand decrement item count - Remove the package from
session.packagesandsession.packageOrder - Clean up related state (target paths, retry state, cached URLs, post-processing)
- Run artifact cleanup in the background (delete downloaded files)
Full changes since v2.0.0-beta.1
See v2.0.0-beta.2 changelog for the 16 code review bugfixes and separate beta identity changes.
-
-
v2.0.0-beta.2 Stable
released this
2026-03-08 19:10:03 +01:00 | 6 commits to main since this releasev2.0.0-beta.2 — Code Review Bugfixes + Separate Beta Identity
Critical Bugfixes (6)
-
Post-processor: double attempts increment — Both
onProgressandonArchiveFailurecallbacks incrementedarchiveState.attempts++, so each extraction failure consumed 2 attempts againstmaxAttempts=3. Effectively reduced retry budget from 3 to 1. Fixed by only incrementing inonArchiveFailure(the authoritative failure path). -
Post-processor: slot leak on abort — When the abort signal fired after
acquireSlot()but before thetry/finallyblock, the early return skippedreleaseSlot(). Each leaked slot permanently reduced extraction parallelism. Fixed by releasing the slot before the early return. -
Scheduler: global watchdog high-water mark never decreases — After a stall event triggered download retries,
bytesAtHeartbeatreset to 0 butlastGlobalProgressBytesstayed at the old peak. SincetotalBytes < lastGlobalProgressByteswas permanently true, the watchdog fired every cycle until downloads exceeded the old peak. Fixed by resetting the high-water mark alongside the timestamp after emittingglobal-stall. -
Pipeline + Download-manager: path traversal in
isPathInsideDir—path.resolve("C:\downloads\pack-evil").startsWith(path.resolve("C:\downloads\pack"))returnedtruebecause no trailing separator was enforced. An attacker-controlled filename could escape the intended directory. Fixed by appendingpath.septo the directory path before thestartsWithcheck. -
Retry-manager: per-kind exhaustion bypassed by shelving — The shelve threshold check (totalFailures ≥ 15) ran before the per-kind exhaustion check (kindCount > maxRetries). Items that exhausted a specific error kind (e.g., 4× NetworkReset with maxRetries=3) would get shelved instead of permanently failed, halving counters and allowing infinite retries. Fixed by checking per-kind exhaustion first.
-
Retry-manager: infinite shelve cycling — No cap on
shelveCount, so items with mixed error kinds could shelve indefinitely (every 15 failures: halve counters → accumulate 15 more → shelve again → forever). AddedMAX_SHELVE_COUNT = 5— after 5 shelve cycles, the item fails permanently.
Important Bugfixes (10)
-
Scheduler: stale retryDelays and providerCooldowns on start() — Previous run's retry delays and provider cooldowns persisted into the next run, causing items to appear delayed or providers to appear cooled down when they shouldn't be. Fixed by clearing both maps in
start(). -
Scheduler: repeated stall-detected events —
checkStalls()re-emittedstall-detectedevery 2 seconds for slots already being aborted (abortReason ≠"none"). Fixed by skipping slots withabortReason !== "none". -
Download-manager:
cleanupAfterExtractionwrong directory —removeDownloadLinkArtifacts()was called withpkg.extractDir(extraction output) instead ofpkg.outputDir(download directory where .lnk files actually are). Link artifacts were never cleaned up. -
Download-manager:
normalizeSessionStatusesmissing "extracting" — On app restart, packages stuck in "extracting" status weren't reset to "queued". They appeared stuck in the UI with no way to restart them. -
Download-manager:
stop()leaves stale activeTasks entries —this.activeTasksmap was never cleared on stop, leaving ghost references to aborted slots. Fixed by addingthis.activeTasks.clear()after aborting all slots. -
Download-manager:
cachedDirectUrlsmemory leak — After a successful download, the direct URL was deleted then immediately re-inserted with the same item ID key. Since completed items never reuse cached URLs, the map grew unbounded. Removed the re-insertion. -
Stream-writer: duplicate truncation code — The same
fs.promises.truncate(effectiveTargetPath, written)block appeared twice in the error path (lines 542-544 and 548-549). Removed the first duplicate. -
Stream-writer: 5-minute drain wait in finally after error —
alignedFlush(true)in thefinallyblock calledwaitDrain()even whenbodyErrorwas already set, potentially blocking for up to 5 minutes on a stuck stream. Fixed by skippingalignedFlushwhen an error already exists. -
Stream-writer: speed limiter stale elapsed after sleep — After the speed limiter's
await sleep(), theelapsedvariable still held the pre-sleep value. The window reset check (elapsed >= 1) used stale data, preventing the speed window from resetting and causing progressively longer sleeps. Fixed by re-readingnowMs()after sleep. -
Error-classifier: missing HTTP 401 and 410 classification — HTTP 401 (Unauthorized) fell through to
Unknowninstead ofForbidden. HTTP 410 (Gone) fell through toUnknowninstead ofNotFound. Added explicit cases for both status codes.
Separate Beta Identity
- appId changed to
com.sucukdeluxe.realdebrid-beta - productName changed to
Real-Debrid-Downloader Beta - package name changed to
real-debrid-downloader-beta - Installs to separate directory (
%APPDATA%/Real-Debrid-Downloader Beta/) - Stable and Beta can run side by side without interfering
Testing
- 216 unit tests passing (1 new test added for per-kind exhaustion priority)
- Existing tests updated to match new shelve/kind-exhaustion priority order and HTTP 401 classification
- Build compiles cleanly (tsup + vite)
-
-
v2.0.0-beta.1 Stable
released this
2026-03-08 18:17:54 +01:00 | 9 commits to main since this releaseDownload System v2 — Complete Rewrite (Beta)
What's New
- Modular architecture: Monolithic download-manager.ts (9,500 lines) split into 7 focused modules
- Typed error classification: 25+ error kinds (DownloadErrorKind enum) replace string matching — errors classified at point of origin
- Declarative retry policies: Per-error-kind policies with exponential backoff, provider cooldowns, and file reset actions
- Reliable resume: Pre-resume file validation (size vs tracker), Range-ignored detection, corrupt file cleanup
- Extraction state machine: Bounded retries (max 3/archive, max 5 rounds/package) — no more infinite loops
- Stall detection: Heartbeat-based per-download monitoring + global watchdog for zero-progress detection
- Shelving mechanism: After 15 total failures, 90s pause + halve counters + switch provider
Architecture (new modules in src/main/download/)
error-classifier.ts— Typed error system, classifier functionsretry-manager.ts— Retry policies, backoff, shelving, state persistencestream-writer.ts— HTTP stream to file, NTFS-aligned buffering, stall detectionpipeline.ts— Single download lifecycle (unrestrict → stream → verify)post-processor.ts— Extraction state machine with bounded retriesscheduler.ts— Queue management, slot allocation, heartbeat monitoringdownload-manager.ts— Drop-in orchestrator (~1,500 lines)
Fixes
- Downloads hanging without clean restart → heartbeat stall detection + global watchdog
- Wrong error classification leading to wrong retry paths → typed DownloadErrorKind enum
- Unreliable resume causing corrupt files → pre-resume validation + Range-ignored detection
- Post-processing extraction breaking or looping → bounded retry state machine
Testing
- 215 new unit tests for error-classifier and retry-manager (all passing)
- Same IPC interface — UI unchanged, drop-in replacement
- Build compiles cleanly