Skip to content

feat: allow removing a task with deletion of downloaded data#139

Merged
linroid merged 2 commits into
mainfrom
feat/remove-with-files
May 20, 2026
Merged

feat: allow removing a task with deletion of downloaded data#139
linroid merged 2 commits into
mainfrom
feat/remove-with-files

Conversation

@linroid
Copy link
Copy Markdown
Owner

@linroid linroid commented May 20, 2026

Summary

Adds an opt-in deleteFiles flag to DownloadTask.remove(). When true,
the engine dispatches to a new DownloadSource.cleanup() hook so each
protocol cleans up its own data:

  • HTTP/FTP: delete the output file via FileAccessor
  • Torrent: call TorrentEngine.removeTorrent(infoHash, deleteFiles = true)

The flag flows through the remote SDK (RemoteDownloadTask) and the daemon
server via a new ?deleteFiles=true query param on DELETE /api/tasks/{id}.
The UI's trash icon now opens a confirmation dialog with an "Also delete
downloaded file" checkbox (resets to unchecked each open) instead of
removing silently. Cleanup is best-effort — failures are logged and never
prevent the task record from being removed.

docs/api.md now documents the full DownloadTask interface including the
new remove(deleteFiles: Boolean = false) signature. Default is false,
so existing callers keep current behavior.

Test Plan

  • task.remove() (no arg) removes only the record, file untouched
  • task.remove(deleteFiles = true) on an in-progress HTTP download deletes the partial file
  • task.remove(deleteFiles = true) on a completed HTTP download deletes the file
  • task.remove(deleteFiles = true) on a torrent invokes removeTorrent(..., deleteFiles = true)
  • When file deletion fails (e.g. permission denied), the task record is still removed and a warning is logged
  • DELETE /api/tasks/{id}?deleteFiles=true removes both record and file
  • DELETE /api/tasks/{id} (no query param) keeps backward-compatible record-only behavior
  • DELETE /api/tasks/{id}?deleteFiles=banana falls back to false
  • UI trash icon opens the confirmation dialog; checkbox resets each open
  • Cancelling the dialog leaves the task untouched

Unit tests cover all of the above except the UI dialog visual behavior
(no UI test infra in this repo today).

Adds an opt-in deleteFiles flag to DownloadTask.remove(). When true,
the engine dispatches to a new DownloadSource.cleanup() hook so each
protocol can tear down its own data (HTTP/FTP delete via FileAccessor;
torrent calls TorrentEngine.removeTorrent(deleteFiles = true)).

The flag flows through the remote SDK and the daemon server via a
new ?deleteFiles=true query param on DELETE /api/tasks/{id}. The UI's
trash icon now opens a confirmation dialog with a checkbox (resets to
unchecked each open) instead of removing the task silently.

Cleanup is best-effort: failures are logged and never prevent the
task record from being removed.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 261a332a83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread library/core/src/commonMain/kotlin/com/linroid/ketch/core/Ketch.kt
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Test Results

1 072 tests  +29   1 072 ✅ +29   13s ⏱️ ±0s
  104 suites +10       0 💤 ± 0 
  104 files   +10       0 ❌ ± 0 

Results for commit a384836. ± Comparison against base commit 729b118.

♻️ This comment has been updated with latest results.

@linroid linroid linked an issue May 20, 2026 that may be closed by this pull request
DownloadCoordinator.cancel() previously called job.cancel() but did not
await the job's finally chain. With remove(deleteFiles = true), the
follow-up cleanup ran while the download's FileAccessor was still being
closed, causing deletion to race the writer (and fail outright on
lock-enforcing platforms like Windows). Capture the job inside the
mutex, then join() outside the mutex so callers see a fully-quiesced
download by the time cancel() returns.

Adds a regression test that pins the ordering by suspending in
source.download() until cancellation, then asserting the download's
finally has run before cancel() returns.

Addresses review feedback on #139.
@linroid linroid merged commit fdaaa6d into main May 20, 2026
8 checks passed
@linroid linroid deleted the feat/remove-with-files branch May 20, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Background downloads and file removal

1 participant