Items incorrectly marked as "completed" by the old 50% recovery threshold
persist in the session file across updates. On startup, check all completed
items: if the file on disk is smaller than expected totalBytes, reset to
"queued" so it gets re-downloaded. Also reset items whose files are missing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs in findReadyArchiveSets disk-fallback:
1. Failed items were explicitly excluded from the blocking check
(status !== "failed"), so partial downloads with "failed" status
would not block extraction. Now ANY non-completed item blocks.
2. The disk size check was only > 10 KB, allowing 627 MB partial
files of 1001 MB archives to pass. Now requires the file to be
within one allocation unit of the item's expected totalBytes.
Added findItemByDiskPath helper to look up the owning item for a
file on disk and get its expected size.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Item-Recovery incorrectly marked partially downloaded files as "completed"
when the file size was >= 50% of expected size. A 627 MB partial download
of a 1001 MB file (62.7%) would pass the check and trigger hybrid
extraction on incomplete RAR archives.
Fix: require file to be within one allocation unit (4 KB) of the expected
size instead of 50%. Also add a pre-allocation guard: if the file appears
to be at the expected size but downloadedBytes is significantly behind
(< 95%), skip recovery (likely a pre-allocated sparse file from a crash).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect items whose targetPath has a " (N)" suffix from the previous
duplicate filename bug and rename them back to the original filename.
This fixes extraction failures for RAR split archives that were
downloaded with (1) suffix before v1.7.19.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After restart, reservedTargetPaths (in-memory) was empty so claimTargetPath
could not distinguish between "file belongs to this item" and "file belongs
to another item". The naive fix (allow overwrite if unclaimed) would have
risked overwriting completed files from other items.
Proper fix: restore reservedTargetPaths from persisted session data on init.
This way each item's targetPath is correctly claimed, and claimTargetPath
can safely reuse the item's own file while protecting other items' files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the app restarts (or updates) while downloads are in progress,
partial files remain on disk but reservedTargetPaths (in-memory) is empty.
claimTargetPath treated the unclaimed-but-existing file as a conflict and
appended (1) to the filename, breaking RAR split archive extraction.
Fix: if a file exists on disk but no other item has reserved the path,
allow overwriting instead of creating a duplicate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shelve (15+ failures) now mimics manual stop/start behavior:
- Clears item.provider for fresh provider selection on retry
- Resets provider circuit breaker (providerFailures) for the old provider
- Reduces shelve duration from 5 min to 90s since the issue is stale
provider state, not a timing problem (manual restart works instantly)
Also adds comprehensive session-load logging:
- Logs package/item count on every session file read
- Logs errors when session file parsing fails (was silent before)
- Safety net: if primary session is empty but backup has packages,
automatically restores from backup
- Logs shutdown save with package/item counts
- Logs DownloadManager init state and cleanup policy
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The inner unrestrict error handler still called recordProviderFailure()
for hosterNotAvailable errors, causing provider-level cooldown escalation
(up to 180s) even though the issue is hoster-side, not provider-side.
This made auto-retry stall while manual reset worked instantly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hosterNotAvailable was added to isTemporaryUnrestrictError which
triggered aggressive provider-level cooldowns (up to 180s) that
blocked ALL items for the affected provider. Since items kept
failing, the cooldown never expired (15-min reset threshold never
reached), causing retries to effectively stall.
Fix: remove hosterNotAvailable from isTemporaryUnrestrictError.
It still gets normal unrestrict retry with item-level backoff
(5s -> 120s) via isUnrestrictFailure, but without provider-wide
cooldown blocking other items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move hosterNotAvailable from isPermanentLinkError to
isTemporaryUnrestrictError — hoster being unavailable is usually
transient (overload, maintenance) and should be retried with backoff
instead of immediately failing as "Link ungültig".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SCENE_EPISODE_RE/JOINED_RE: use (?!\d) lookahead instead of requiring
separator after episode number, so filenames like s09e06rrp now match
- MKV-Sammelordner: skip 0-byte files from failed/partial extractions
- MKV-Sammelordner: detect same-name same-size duplicates in target dir
and skip instead of creating (2) copies; remove duplicate source file
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Retry failed wrong_password archives serially after parallel extraction
to recover from CRC mismatches caused by concurrent UnRAR I/O contention
- Stop resetting sessionDownloadedBytes on start/resume so the session
total accurately reflects all bytes downloaded since app launch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Daily traffic limits:
- Per-provider daily download limit (configurable in GB per provider)
- Per Debrid-Link API key daily limit (individual limits per key)
- Usage tracking with automatic daily reset at midnight
- Provider is skipped when daily limit reached, falls back to next provider
- Reset button per provider and per Debrid-Link key in account settings
- Hoster routing skips daily-limited providers gracefully
Debrid-Link multi-key improvements:
- Keys now display with labels (#1, #2...) and masked tokens in account list
- Option to show detailed per-key view with individual usage stats
- Keys that hit their daily limit are automatically skipped
- providerAccountId/providerAccountLabel stored per download item
Auto-sort packages by progress:
- Active packages automatically sorted to top during downloads
- Sorted by completion ratio, then downloaded bytes
- Toggle in settings (autoSortPackagesByProgress)
UI polish:
- Package column headers: flatter, more transparent design
- LinkSnappy mode label: "Login" renamed to "Web"
- Account list: new toggle for detailed Debrid-Link key display
- Account usage stats section with warning styling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- extractor: detect UnRAR "Cannot create...\..." error (archive with
leading-backslash internal paths) and retry in flat mode (-e) which
strips all paths and avoids the invalid double-separator on Windows
- types/download-manager: add providerLabel field to DownloadItem,
store full label (e.g. "Debrid-Link #1") set at unrestrict time
- App: display providerLabel in Service column (falls back to generic
provider name if label not yet set)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sanitizeFilename() is now applied before constructing outputDir and
extractDir, so names like "TMSF/4SF" no longer produce broken Windows paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a pending item has neither targetPath nor fileName (e.g. after a
reset before re-unrestrict), it is invisible to pendingItemStatus and
the disk-fallback could incorrectly start extraction with a partial file.
Add a guard that skips disk-fallback for any archive set if the package
contains such an untracked pending item.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Clear item.provider on stop/restart so provider order/routing changes
are respected on next download attempt
- Reset item.provider for all non-completed items when providerOrder or
hosterRouting changes in settings
- Cancel scheduled-start timer when queue is started manually
- Track disk-fallback hybrid-extract archives per session to prevent
infinite post-processing loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MKV library collection now filters out sample files before moving.
Files in "sample"/"samples" directories and files with "sample" in
their name are excluded. This prevents duplicate "(2)" entries in
the library folder caused by samples having the same base name as
the real episodes (just different casing from the archive).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace BrowserWindow-based login flow with Netscape cookie file import
for BestDebrid authentication. Cloudflare Turnstile captcha cannot be
solved in Electron's embedded browser, so users export cookies from
their real browser and import them here.
- Rewrite bestdebrid-web.ts: remove BrowserWindow/CDP code, add
parseNetscapeCookieFile() and importCookiesFromFile()
- Add file picker dialog for .txt cookie files in main IPC handler
- Update IPC channel from OPEN_BESTDEBRID_LOGIN to IMPORT_BESTDEBRID_COOKIES
- Update preload bridge and renderer UI with cookie import button
- Fix pLabel scope in downloadToFile (pass as parameter from processItem)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The running download status (e.g. "Download läuft", "Warte auf
Festplatte") now shows the full provider label including the source
mode, e.g. "Mega-Debrid (API)" instead of just "Mega-Debrid".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When hybrid extraction handled all archives, extractedCount stayed 0
causing all cleanup steps (archive deletion, resume state, link/sample
removal, empty dir pruning, auto-rename, nested extraction) to be
bypassed. Extended conditions to also trigger on alreadyMarkedExtracted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace extractSlow() per-item extraction with IInArchive.extract() bulk API
in 7-Zip-JBinding. Solid RAR archives no longer re-decode from the beginning
for each item, bringing extraction speed close to native WinRAR/7z.exe (~375 MB/s
instead of ~43 MB/s).
- Add BulkExtractCallback implementing both IArchiveExtractCallback and
ICryptoGetTextPassword for proper password handling during bulk extraction.
- Fix resolveArchiveItemsFromList with multi-level fallback matching:
1. Pattern match (multipart RAR, split ZIP/7z, generic splits)
2. Exact filename match (case-insensitive)
3. Stem-based fuzzy match (handles debrid service filename modifications)
4. Single-item archive fallback
- Simplify caching from Set+Array workaround back to simple Map<string, T>
(the original "caching failure" was caused by resolveArchiveItemsFromList
returning empty arrays, not by Map/Set/Object data structure bugs).
- Add comprehensive tests for archive item resolution (14 test cases)
and JVM extraction progress callbacks (2 test cases).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- JVM extractor now supports --daemon mode: starts once, processes
multiple archives via stdin JSON protocol, eliminating ~5s JVM boot
per archive
- TypeScript side: daemon manager starts JVM once, sends requests via
stdin, falls back to spawning new process if daemon is busy
- Fix extraction progress caching: replaced Object.create(null) + in
operator with Set<string> + linear Array scan — both Map.has() and
the in operator mysteriously failed to find keys that were just set
- Daemon auto-shutdown on app quit via shutdownDaemon() in before-quit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace Map-based archive item cache with plain Object.create(null)
to work around mysterious Map.has() returning false despite set()
being called with the same key — this caused resolveArchiveItems
to run on every 1.1s pulse instead of being cached, preventing
extraction progress (Entpacken X%) from ever showing in the UI
- Apply same fix to both hybrid and full extraction paths
- Increase JVM heap from 512MB to 1GB for better extraction throughput
- Use SerialGC for faster JVM startup on short-lived extract processes
- Add download lifecycle logging (package add + item download start)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Log when packages are added (count + names)
- Log when individual item downloads start (filename, size, provider)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change OS priority from IDLE/BELOW_NORMAL to NORMAL/BELOW_NORMAL so
extraction runs at full speed (matching manual 7-Zip/WinRAR performance)
- Use "high" priority in both hybrid and full extraction paths
- Increase hybrid extraction threads from hardcoded 2 to dynamic
calculation (half CPU count, min 2, max 8)
- Fix emitState forced emit being silently dropped when a non-forced
timer was already pending — forced emits now always replace pending
timers to ensure immediate UI feedback during extraction transitions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Force immediate emitState when first resolving archive items so UI
transitions from 'Ausstehend' to 'Entpacken X%' instantly
- Use BELOW_NORMAL priority (instead of IDLE) for final extraction
when all downloads are complete — matches manual extraction speed
- Add diagnostic logging for resolveArchiveItems matching
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "Download fertig: filename (size), pkg=name" log line when an item
finishes downloading, enabling precise timing analysis of when archive
parts become available for extraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Run collectMkvFilesToLibrary in background after each hybrid extraction
round so MKVs are moved to the library as episodes are extracted, not
only after the entire package finishes
- Add timing logs to identify bottlenecks:
- Post-process slot wait time
- Per-round duration with requeue status
- Recovery loop duration
- Setup time in handlePackagePostProcessing
- findReadyArchiveSets duration when > 200ms
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After a hybrid extraction round completes, set the requeue flag so the
do-while loop immediately checks for more ready archive sets. Previously,
if all items completed before the task started processing, the single
requeue flag was consumed and no new completions triggered re-extraction,
causing 25+ second gaps until the next download completion.
Also change runHybridExtraction return type from void to number
(extracted count) to enable conditional self-requeue only when archives
were actually extracted, preventing infinite requeue loops.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Release post-process slot immediately after main extraction completes.
All slow post-extraction work (nested extraction, auto-rename, archive
cleanup, link/sample removal, empty directory cleanup, MKV collection)
now runs in background via runDeferredPostExtraction so the next package
can start unpacking without delay.
- Export hasAnyFilesRecursive, removeEmptyDirectoryTree, cleanupArchives
from extractor.ts for use in deferred handler
- Import removeDownloadLinkArtifacts, removeSampleArtifacts from cleanup
- Expand runDeferredPostExtraction with full post-cleanup pipeline:
nested extraction, rename, archive cleanup, link/sample removal,
empty dir tree removal, resume state clearing, MKV collection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix ~70 issues across the entire codebase including security fixes,
error handling improvements, test stabilization, and code quality.
- Fix TLS race condition with reference-counted acquire/release
- Bind debug server to 127.0.0.1 instead of 0.0.0.0
- Add overall timeout to MegaWebFallback
- Stream update installer to disk instead of RAM buffering
- Add path traversal protection in JVM extractor
- Cache DdownloadClient with credential-based invalidation
- Add .catch() to all fire-and-forget IPC calls
- Wrap app startup, clipboard, session-log in try/catch
- Add timeouts to container.ts fetch calls
- Fix variable shadowing, tsconfig path, line endings
- Stabilize tests with proper cleanup and timing tolerance
- Fix installer privileges, scripts, and afterPack null checks
- Delete obsolete _upload_release.mjs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After an archive finishes at 100%, show "Naechstes Archiv..." label
while the next archive initializes, eliminating the "dead" gap where
no activity was visible between consecutive extractions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show "Entpacken vorbereiten..." while scanning archives and checking disk space
- Show "Archive scannen..." and "Speicherplatz prüfen..." phases from extractor
- Use dash separator in UI: "[10/10 - Done] - Entpacken 45% (3/6)"
- Handle new "preparing" phase in both hybrid and full extraction progress handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update postProcessLabel during extraction with detailed progress:
- Overall percentage and archive count (e.g. "Entpacken 45% (3/6)")
- Password cracking progress when testing passwords
- Works for both hybrid and full extraction modes
Previously the label was static "Entpacken..." with no detail about
what was happening during potentially long extraction phases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DDownload's storage servers (dstorage.org) use certificates that fail
Node.js TLS verification. Add skipTlsVerify flag to UnrestrictedLink
and temporarily disable TLS verification for the download fetch when
the flag is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DDownload (ddownload.com/ddl.to) as new hoster with web login
- Post-processing labels: Entpacken/Renaming/Aufräumen/MKVs
- Release notes shown in update confirmation dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When hybrid extraction finds no ready archive sets (because remaining parts
are still downloading), completed items were incorrectly labeled as
"Entpacken - Ausstehend" instead of "Entpacken - Warten auf Parts".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix post-process slot counter going negative after stop(), allowing multiple
packages to extract simultaneously instead of one at a time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix "Fertig" status on completed items: session recovery no longer resets
"Entpacken - Ausstehend" to "Fertig (size)" — respects autoExtract setting
- Extraction continues during pause instead of being aborted
- Hybrid extraction recovery on start/resume: triggerPendingExtractions and
recoverPostProcessingOnStartup now handle partial packages with hybridExtract
- Move Up/Down buttons: optimistic UI update so packages move instantly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add proactive disk-busy detection: lower STREAM_HIGH_WATER_MARK from 2 MB
to 512 KB so backpressure triggers sooner, and monitor stream.writableLength
to show "Warte auf Festplatte" after 300 ms of undrained writes — before
actual backpressure hits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix hybrid extraction stalling: requeue loop now keeps the post-process
slot so the same package re-runs immediately without waiting behind other
packages. Also skip already-extracted archives on requeue rounds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix hybrid extract not using maxParallelExtract setting (was hardcoded to 1)
- Fix "Warten auf Parts" label shown for items whose downloads are already complete
- Update hybrid extract progress handler to support parallel archive tracking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
maxParallelExtract now controls how many archives extract simultaneously
within a single package (e.g. 4 episodes at once). Packages still
extract sequentially (one package at a time) to focus I/O. Progress
handler updated to track multiple active archives independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously maxParallelExtract allowed multiple packages to extract
simultaneously, splitting I/O across packages. Now packages extract
one at a time in packageOrder so each package finishes faster.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fortschritt column is now clickable/sortable (ascending/descending by package %)
- Extraction queue respects packageOrder: top packages get extracted first
- Packages currently extracting are auto-expanded so user can see progress
- Increased Fortschritt column width for better spacing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New setting maxParallelExtract in AppSettings
- UI input in Entpacken tab: "Parallele Entpackungen"
- Replaces hardcoded maxConcurrent=2 in acquirePostProcessSlot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous targetPath-only matching missed items whose targetPath
differed from the on-disk filename. Now matches by basename and
fileName for reliable archive-part to item association.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace serial packagePostProcessQueue with semaphore (max 2 concurrent)
- Hybrid-extract: items waiting for parts show "Entpacken - Warten auf Parts"
- Failed hybrid extraction shows "Entpacken - Error" instead of "Fertig"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
findNextQueuedItem(), hasQueuedItems(), hasDelayedQueuedItems() and
countQueuedItems() now skip packages not in runPackageIds when the set
is non-empty. This ensures "Ausgewählte Downloads starten" only
processes selected packages instead of all enabled ones.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Restore all source files from v1.5.49 (proven stable on both servers)
- Add startPackages() IPC method that starts only specified packages
- Fix context menu "Ausgewählte Downloads starten" to use startPackages()
instead of start() which was starting ALL enabled packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require near-complete file size checks in Item-Recovery and hybrid ready-set detection so partially downloaded RAR parts are not marked completed and extracted prematurely.
The previous fix blocked ALL multi-part extractions when any item in the
package was pending. Now checks only parts of the SAME archive (by prefix
match on fileName/targetPath), so E01 can extract while E06 downloads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- findReadyArchiveSets: for .part1.rar, require ALL package items
to be terminal before allowing extraction (prevents premature
extraction when later parts have no targetPath/fileName yet)
- JVM extractor: remove CRCERROR from isPasswordFailure() — only
DATAERROR indicates wrong password. CRCERROR on archives where
7z-JBinding falsely reports encrypted no longer triggers password
cycling.
- looksLikeWrongPassword: remove CRC text matching, keep only
explicit "data error" for encrypted archives.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Account Manager: table UI with add/remove/check for all 4 providers
(Real-Debrid, Mega-Debrid, BestDebrid, AllDebrid)
- Backend: checkRealDebridAccount, checkAllDebridAccount, checkBestDebridAccount
- Hybrid-Extract fix: check item.fileName for queued items without targetPath,
disable disk-fallback for multi-part archives, extend disk-fallback to catch
active downloads by fileName match (prevents CRC errors on incomplete files)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- normalizeSessionStatuses: reset all queued items to "Wartet" instead of
only checking a few specific patterns (missed Retry, Unrestrict-Fehler etc.)
- Reset completed items with stale extraction status to "Fertig (size)"
- stop(): reset all non-finished items to queued/"Wartet" and packages to queued
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add disk space check before extraction (aborts if insufficient space)
- Add single-level nested archive extraction (archives inside archives)
- Blacklist .iso/.img/.bin/.dmg from nested extraction
- Set real Windows I/O priority (Very Low) on UnRAR via NtSetInformationProcess
- Reduce UnRAR threads to -mt1 during hybrid extraction
- Fix double episode renaming (s01e01e02 pattern)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Items with transient status texts like Provider-Cooldown, Warte auf
Daten, Verbindungsfehler are reset to "Wartet" when the app restarts,
so they don't show misleading status from a previous session.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Debounce: simultaneous failures within 2s count as 1 failure
(prevents 8 parallel unrestrict failures from instant-triggering)
- Raise threshold from 8 to 20 consecutive failures before cooldown
- Escalation tiers: 20→30s, 35→60s, 50→120s, 80+→300s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
- Add pause check at top of processItem retry loop so items show
"Pausiert" instead of "Provider-Cooldown" when paused
- Lower extraction process priority from BELOW_NORMAL to IDLE
(IDLE_PRIORITY_CLASS on Windows also lowers I/O priority, reducing
disk contention between extraction and active downloads)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make saveSettings async to stop blocking the event loop during downloads
- Add 120ms minimum gap for forced state emissions to prevent rapid-fire IPC
- Fix circuit breaker feedback loop: reset failure count after cooldown expires
- Add 120s time-decay for failure counter (transient bursts don't snowball)
- Raise circuit breaker threshold from 5 to 8 consecutive failures
- Stop counting network stalls as provider failures
- Items without a provider only check primary provider cooldown, not all
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New "Jetzt entpacken" right-click option: triggers extraction for
completed packages regardless of paused/stopped state
- Fix 5-10s freeze when pressing Start after Pause: recoverRetryableItems
was calling fs.stat on every item (474+); now only checks failed/completed
- Full IPC pipeline: extractNow in manager, controller, preload, renderer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Right-click packages with extraction errors shows "Extraktion
wiederholen" option to manually retry
- Increase WinRAR error text from 240 to 500 chars for better
diagnostics in logs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- triggerPendingExtractions() now runs when unpausing, so packages
with extraction errors are automatically retried
- executeDeleteSelection no longer depends on snapshot objects
(prevents unnecessary re-renders with large queues)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Session counter now uses sessionDownloadedBytes (in-memory counter)
instead of summing completed items. Removing packages after extraction
no longer resets the session total.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Save settings every 30s during active downloads (not just session)
- Force settings save on shutdown and run finish
- Preserve live totalDownloadedAllTime when user saves settings
(app-controller's stale copy no longer overwrites the counter)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pause button is now one-way (orange glow when paused, disabled when
already paused). Start button resumes from pause.
- Fix hybrid extraction attempting incomplete multi-part archives when
paused: disk-fallback now blocks any non-terminal item status, not
just downloading/validating/integrity_check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track totalDownloadedAllTime in settings (persists across restarts)
- Track sessionDownloadedBytes for current app session
- Status bar shows both: Session + Gesamt
- Statistics section shows Heruntergeladen (Session) + (Gesamt)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track packageId in speed events so package speed uses same 3-second
window as global speed (fixes mismatch between package and status bar)
- Add packageSpeedBps to UiSnapshot, computed from speed events
- Context menu delete actions now respect confirmDeleteSelection setting
- Progress bar visible even when package is collapsed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dead link detection:
- Mega-Web: parse hoster error messages (hosterNotAvailable, etc.) from HTML
and throw specific error instead of returning null
- MegaDebridClient: stop retrying on permanent hoster errors
- download-manager: isPermanentLinkError() immediately fails items with dead
links instead of retrying forever
Extraction race condition:
- package_done cleanup policy checked if all items were "completed" (downloaded)
but not if they were "extracted" — removing the package before the last
episode could be extracted
- Both applyCompletedCleanupPolicy and applyPackageDoneCleanup now guard
against premature removal when autoExtract is enabled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- HTTP 200 on resume: detect server ignoring Range header, write in truncate mode
instead of appending (prevents doubled/corrupted files)
- HTTP 416 without Content-Range: assume complete if >1MB exists instead of
deleting potentially multi-GB finished files
- Stream handle leak: explicit destroy() after finally to prevent fd exhaustion
- Drain timeout: don't abort controller on disk backpressure, let inner retry
loop handle it instead of escalating to full stall pipeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Provider circuit breaker: track consecutive failures per provider with
escalating cooldowns (30s/60s/120s/300s), auto-invalidate Mega-Debrid
session on cooldown
- Escalating backoff: retry delays now scale up to 120s (was 30s max),
unrestrict backoff exponential instead of linear 15s cap
- Shelve logic: after 15 consecutive failures, item pauses 5 min with
counter halving for gradual recovery
- Periodic soft-reset: every 10 min, reset stale retry counters (>10 min
queued) and old provider failures (>15 min), acts like mini-restart
- Mega-Debrid queue timeout: 90s wait limit in runExclusive to prevent
cascade blocking behind stuck calls
- Provider-cooldown-aware retry delays: items wait for provider cooldown
instead of retrying against broken service
- Fix: reconnect/package_toggle now persist retry counters (previously
lost on interruption, defeating shelve logic)
- Mega-Debrid generate: tighter timeouts, progressive reload backoff,
hoster retry limit (5x max)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Some hosters return tiny error responses (e.g. 9 bytes) with HTTP 200.
- downloadToFile: detect files <512 B, log content, delete and throw for retry
- Post-download: catch <512 B files even when totalBytes is unknown
- Logs the error-page content for debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep existing good filename when debrid API returns "download.bin"
or opaque name. Only overwrite item.fileName if the resolved name
is actually better (not opaque, not download.bin).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When post-processing runs, detect items in idle states (queued/paused)
whose target file already exists on disk with non-zero size, and
auto-recover them to "completed" status. This ensures allDone becomes
true, triggering final extraction with archive cleanup (delete mode).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add disk-fallback to findReadyArchiveSets: when all archive parts
physically exist on disk with non-zero size and none are actively
downloading/validating, consider the archive ready for extraction.
This fixes episodes being skipped when a download item's status
was not updated to "completed" despite the file being fully written.
Also improve debug server: raise log limit to 10000 lines,
add grep filter, add /session endpoint for raw session data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The validating-stuck timeout (45s) was shorter than the unrestrict
timeout (60s), causing items to be endlessly aborted and retried
before the debrid API call could complete. Now uses unrestrict
timeout + 15s buffer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert all sync FS ops (existsSync, readdirSync, statSync, writeFileSync,
rmSync, renameSync) to async equivalents across download-manager, extractor,
cleanup, storage, and logger to prevent UI freezes
- Replace linear retry delays with exponential backoff + jitter to prevent
retry storms with many parallel downloads
- Deduplicate resolveArchiveItems into single shared function
- Replace Array.shift() O(N) in bandwidth chart with slice-based trimming
- Make logger rotation async in the async flush path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Don't clear extraction resume state during hybrid mode (skipPostCleanup)
- Mark ALL completed items as "Entpackt" after successful hybrid extraction
to prevent full extraction from re-extracting already-extracted archives
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>