• v2.0.0-beta.5 0a7467a8b0
  • v2.0.0-beta.4 25b7104580

    v2.0.0-beta.4 Stable

    Administrator released this 2026-03-08 19:19:32 +01:00 | 2 commits to main since this release

    v2.0.0-beta.4 — Fix Auto-Updater

    Bugfix

    • Auto-updater pointed to stable repo instead of beta repo — DEFAULT_UPDATE_REPO in constants.ts was still set to Administrator/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 to Administrator/beta-real-debrid-downloader so 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.

    Downloads
  • v2.0.0-beta.3 4df0d40ece

    v2.0.0-beta.3 Stable

    Administrator released this 2026-03-08 19:16:38 +01:00 | 4 commits to main since this release

    v2.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 from session.packages, session.items, or session.packageOrder. The old download-manager called removePackageFromSession() 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.items and decrement item count
      • Remove the package from session.packages and session.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.

    Downloads
  • v2.0.0-beta.2 ab08506361

    v2.0.0-beta.2 Stable

    Administrator released this 2026-03-08 19:10:03 +01:00 | 6 commits to main since this release

    v2.0.0-beta.2 — Code Review Bugfixes + Separate Beta Identity

    Critical Bugfixes (6)

    • Post-processor: double attempts increment — Both onProgress and onArchiveFailure callbacks incremented archiveState.attempts++, so each extraction failure consumed 2 attempts against maxAttempts=3. Effectively reduced retry budget from 3 to 1. Fixed by only incrementing in onArchiveFailure (the authoritative failure path).

    • Post-processor: slot leak on abort — When the abort signal fired after acquireSlot() but before the try/finally block, the early return skipped releaseSlot(). 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, bytesAtHeartbeat reset to 0 but lastGlobalProgressBytes stayed at the old peak. Since totalBytes < lastGlobalProgressBytes was permanently true, the watchdog fired every cycle until downloads exceeded the old peak. Fixed by resetting the high-water mark alongside the timestamp after emitting global-stall.

    • Pipeline + Download-manager: path traversal in isPathInsideDir — path.resolve("C:\downloads\pack-evil").startsWith(path.resolve("C:\downloads\pack")) returned true because no trailing separator was enforced. An attacker-controlled filename could escape the intended directory. Fixed by appending path.sep to the directory path before the startsWith check.

    • 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). Added MAX_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-emitted stall-detected every 2 seconds for slots already being aborted (abortReason ≠ "none"). Fixed by skipping slots with abortReason !== "none".

    • Download-manager: cleanupAfterExtraction wrong directory — removeDownloadLinkArtifacts() was called with pkg.extractDir (extraction output) instead of pkg.outputDir (download directory where .lnk files actually are). Link artifacts were never cleaned up.

    • Download-manager: normalizeSessionStatuses missing "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.activeTasks map was never cleared on stop, leaving ghost references to aborted slots. Fixed by adding this.activeTasks.clear() after aborting all slots.

    • Download-manager: cachedDirectUrls memory 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 the finally block called waitDrain() even when bodyError was already set, potentially blocking for up to 5 minutes on a stuck stream. Fixed by skipping alignedFlush when an error already exists.

    • Stream-writer: speed limiter stale elapsed after sleep — After the speed limiter's await sleep(), the elapsed variable 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-reading nowMs() after sleep.

    • Error-classifier: missing HTTP 401 and 410 classification — HTTP 401 (Unauthorized) fell through to Unknown instead of Forbidden. HTTP 410 (Gone) fell through to Unknown instead of NotFound. 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)
    Downloads
  • v2.0.0-beta.1 36dc6040ba

    v2.0.0-beta.1 Stable

    Administrator released this 2026-03-08 18:17:54 +01:00 | 9 commits to main since this release

    Download 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 functions
    • retry-manager.ts — Retry policies, backoff, shelving, state persistence
    • stream-writer.ts — HTTP stream to file, NTFS-aligned buffering, stall detection
    • pipeline.ts — Single download lifecycle (unrestrict → stream → verify)
    • post-processor.ts — Extraction state machine with bounded retries
    • scheduler.ts — Queue management, slot allocation, heartbeat monitoring
    • download-manager.ts — Drop-in orchestrator (~1,500 lines)

    Fixes

    1. Downloads hanging without clean restart → heartbeat stall detection + global watchdog
    2. Wrong error classification leading to wrong retry paths → typed DownloadErrorKind enum
    3. Unreliable resume causing corrupt files → pre-resume validation + Range-ignored detection
    4. 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
    Downloads