Commit Graph

23 Commits

Author SHA1 Message Date
NimBold 50c3da2f5d fix(downloads): close media lifecycle cleanup gaps
Validate every Aria2 mirror URI, keep metadata cleanup errors truthful, and serialize media registration with lifecycle cancellation so abandoned tombstones cannot accumulate.
2026-07-17 01:03:52 +03:30
NimBold 2479ead4ed fix(downloads): harden lifecycle race handling
Audit Assignment 06 lifecycle paths and preserve truthful state across ambiguous Aria2 resume failures. Clean up partial startup listener registration and prevent stale resume workers from leaking or releasing current permits.
2026-07-15 05:34:32 +03:30
NimBold e8487ee71b fix(downloads): harden lifecycle cancellation races 2026-07-15 00:10:56 +03:30
NimBold e07182fbf2 fix(downloads): harden queue and lifecycle synchronization
Serialize queue controls, make multi-item moves atomic, await stale enqueue cleanup, and guard late media and progress events. Add deterministic table sorting and regression coverage for worst-case lifecycle races.
2026-07-14 18:29:14 +03:30
NimBold 757e313f71 fix(download): require aria2 for file transfers
Update yt-dlp to 2026.07.04 and refresh the bundled macOS runtime plus engine locks.

Route every non-media download through aria2 by removing the native HTTP fallback path, native GID handling, and the old direct-download harness.

Retry transient aria2 startup/RPC failures before failing, then show the real last error in the download row and Properties modal so Windows failures are diagnosable instead of silent.

Refresh docs and tests around the aria2-only file-download contract, and advance the Firefox extension submodule to its published wording cleanup.
2026-07-05 20:00:53 +03:30
NimBold cfb5a5b6e0 fix(settings): harden network controls 2026-07-02 15:43:53 +03:30
NimBold 1e61d05873 fix(download): honor retry and queue limits
Treat max_tries as the configured retry count instead of total attempts across native, media, aria2, and fallback paths.

Route queue slot acquisition through retirement-aware permit handling so shrinking concurrency does not dispatch new work while active transfers still meet the smaller limit.

Update retry-budget and queue-manager tests to cover the corrected attempt counts and paused aria2 resume behavior.
2026-07-02 01:58:30 +03:30
NimBold e03a3b5dbb style: run cargo fmt to resolve CI failure 2026-06-25 00:46:21 +03:30
NimBold b3f4074d67 fix: resolve low severity vulnerabilities from deepseek audit 2026-06-25 00:41:43 +03:30
NimBold 187d70f348 fix: resolve bugs introduced during high severity vulnerability remediation 2026-06-24 23:59:38 +03:30
NimBold 00e84d6935 fix: resolve 12 HIGH severity vulnerabilities from audit 2026-06-24 23:48:35 +03:30
NimBold ddd4662898 fix(network): explicitly disable proxy fallbacks for none and system modes
Disabled implicit system/environment variable proxy fallbacks in reqwest, yt-dlp, and aria2c when no proxy is explicitly provided. Updated useDownloadStore to strictly return 'none' when 'none' is selected or when 'system' proxy is empty, matching IDM/FDM behavior and ignoring http_proxy environment variables.
2026-06-23 04:21:25 +03:30
NimBold 6b3753949b fix(downloads): support offline fallback drafts
- launch Firefox handoffs through authenticated reconnect
- preserve usable drafts when metadata lookup fails
- reject stale metadata results and retry failed rows only
2026-06-22 17:22:21 +03:30
NimBold 06b14df307 fix(core): harden download lifecycle and scheduling 2026-06-22 11:19:18 +03:30
NimBold 894c238bb7 feat(queue): implement concurrent deduplication and safe backend detachment
- Add backendRegisteredIds and backendDispatchPromises for single dispatch enforcement

- Add detach_download_for_reconfigure to safely modify properties of active downloads

- Add applyProperties logic handling completed, failed, paused, and active queues

- Add extractValidDownloadUrls and fix multi-url paste handling

- Setup vitest and add useDownloadStore unit tests for backend registration lifecycle
2026-06-20 11:41:55 +03:30
NimBold 85df857678 fix(ytdlp): correct media size estimates 2026-06-19 16:41:33 +03:30
NimBold cb39113117 feat(observability): add centralized diagnostics logging engine and native log viewer panel
- Configure tauri-plugin-log with 10MB rotation and 3-file retention
- Add high-frequency format filter to strip [download]% progress ticks
- Hook yt-dlp, aria2c, and native reqwest runners with lifecycle log macros
- Add export_logs Tauri command for async log file export via save dialog
- Create DiagnosticsView React component with streaming monospace console
- Apply severity highlighting: ERROR=red, WARN=yellow, INFO=grey, DEBUG=dim
- Wire Diagnostics tab into sidebar navigation and ActiveView routing
- Log native download failures to log::error! in download.rs
2026-06-17 10:57:32 +03:30
NimBold 7c7317adc9 fix(retry): honor attempt caps per download URL 2026-06-17 09:27:17 +03:30
NimBold f6851682dd feat(retry): add connection-aware exponential backoff across all download backends
Transient network drops and Wi-Fi timeouts no longer promote a download
straight to a hard Failed state. A shared retry engine classifies the
error, emits a transient `Retrying` state, and runs a 3-strike
exponential backoff (2s / 5s / 10s) while preserving the active download
allocation (semaphore permit / worker slot). Resumability primitives are
reused on every retry so no downloaded bytes are discarded.

Engine core (src-tauri/src/retry.rs, new):
- BACKOFF_SCHEDULE = [2s, 5s, 10s], MAX_RETRIES = 3
- backoff_for(strike): schedule index with graceful clamp beyond range
- is_transient_network_error(msg): string classifier covering reqwest,
  yt-dlp, and aria2c phrasing; permanent conditions (HTTP 401/403/404/
  410/451, not-found, permission denied, out-of-disk) checked first so
  they always fail fast
- backoff_and_emit / backoff_and_emit_cancel: cancel-safe sleep helpers
  driving a Retrying state emit before each delay
- 9 unit tests covering schedule math, clamping, transient vs permanent
  classification, and permanent-wins-over-transient precedence

State model (src-tauri/src/ipc.rs):
- DownloadStatus::Retrying variant (serialized "retrying")
- DownloadStateEvent::retrying(id, reason) constructor
- Regenerated TypeScript binding: src/bindings/DownloadStatus.ts

Native reqwest backend (src-tauri/src/download.rs):
- DownloadEvent::Retrying variant (headless mirror)
- CoordinatorEventSink::emit_retrying() drives the production
  download-state channel with status "retrying"
- download_file retry core rewritten: transient -> emit_retrying ->
  backoff_for sleep inside a control_rx select (pause/cancel honored
  mid-backoff) -> re-issue Range header; permanent errors or strike
  exhaustion advance to the next URL then hard Failed

yt-dlp media backend (src-tauri/src/lib.rs):
- child spawn+stream loop wrapped in a 3-strike re-spawn loop; stderr
  tail classified and, if transient, the process is re-spawned after
  backoff (--continue resumes); --retry-wait=2 added to aria2c downloader

aria2c backend (src-tauri/src/queue.rs):
- retry-wait=2 option so aria2's internal retries are not rapid-fire
- handle_aria2_download_error: intercepts transient onDownloadError,
  backs off, re-issues addUri, and rotates the stale gid -> id mapping
  via rotate_aria2_gid (fresh addUri mints a new gid; not rotating would
  detach subsequent WS events and leak the semaphore permit permanently)
- aria2_payloads / aria2_retry_strikes tracking with cleanup on terminal
  outcomes

Verification: cargo build clean; cargo test --lib 37 passed / 0 failed.
2026-06-17 09:16:17 +03:30
NimBold b6678493d3 fix(backend): resolve clippy warnings breaking CI pipeline 2026-06-16 11:21:26 +03:30
NimBold 601b04c4cb fix: implement aria2 polling to prevent UI from sticking on queued 2026-06-15 17:51:32 +03:30
NimBold 9e26be5b2c fix: app nap ipc drop and implement delete modal 2026-06-15 13:29:20 +03:30
NimBold 6593f9e76a refactor(repo): promote tauri app to repository root 2026-06-15 10:33:40 +03:30