feat(seedbox): autoclean torlink records whose files are gone - #148
Merged
Conversation
torlink never forgets a torrent. Its records survive restarts and outlive
the data by design, so a box that has had files deleted accumulates ghost
entries forever — the live seedbox reported 63 torrents for 39
directories on disk, 40 of them paused records for data that no longer
exists.
The status page already hid them, but hiding is not fixing: torlink's own
count kept drifting further from reality, and every one of those ghosts
is still offered "start seeding" in the UI.
Visiting Torlink status now prunes them once per visit, and the amber
"hidden torrents" block gets an explicit button for it.
Safety, since being wrong here destroys a record rather than hiding a row:
- always `remove`, never `delete`. `delete` asks torlink to unlink the
files; `remove` only forgets the record. A bug in the staleness check
therefore cannot destroy data.
- refuses to prune unless the on-disk listing was read successfully AND
is non-empty. An empty listing is indistinguishable from a file
server pointed at the wrong directory, and pruning against it would
erase every record on the box.
- only stored states (seeding/paused) and torlink's own `missing`
verdict qualify. Downloading, queued, failed and unrecognised states
are never pruned — they have no files *yet*.
- autoclean runs at most once per mount; the poll re-renders every few
seconds and would otherwise fire an endless stream of control calls.
- control calls are sequential, not concurrent: this daemon is already
known to wedge, and a tidy-up must not become an outage.
Also deduplicates listOnDiskNames, which the status route and cleanup
both needed, into files.ts alongside the other file-server helpers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
torlink never forgets a torrent. Records survive restarts and outlive the data by design, so a box that has had files deleted accumulates ghosts forever. On the live seedbox:
The status page already hid those 40, but hiding isn't fixing — torlink's own count keeps drifting from reality, and every ghost is still offered a "start seeding" button for data that isn't there.
What
Visiting Torlink status now prunes stale records once per visit. The amber "hidden torrents" block also gets an explicit button:
Uses torlink 1.4.4's control API:
POST /control { id, action: 'remove' }.Safety
Being wrong here destroys a record rather than merely hiding a row, so the guards are deliberately strict:
remove, neverdeletedeleteunlinks files;removeonly forgets. A bug in the staleness check cannot destroy data.seeding/paused/ torlink's ownmissingdownloading,queued,failedand unrecognised states have no files yet and are never pruned.404from torlink counts as successAlso
Deduplicates
listOnDiskNames, which the status route and cleanup both needed, intofiles.tsbeside the other file-server helpers.Tests
src/lib/seedbox/cleanup.test.ts— 13 cases, with a dedicated block for "refuses to prune without trustworthy ground truth" covering the unreadable-listing, empty-listing, in-flight/failed, unreadable-status and missing-id paths. PlusisStaleTorrentintorlink-reconcile.ts.Full suite: 181 files, 2494 passed, clean
tsc --noEmit.Two
react-hooks/set-state-in-effectwarnings (not errors) remain intorlink-status.tsx— one pre-existing on the poll effect, one on the new autoclean effect, which follows the same established pattern in that file.🤖 Generated with Claude Code