Skip to content

feat(seedbox): autoclean torlink records whose files are gone - #148

Merged
ralyodio merged 1 commit into
masterfrom
feat/seedbox-autoclean
Jul 31, 2026
Merged

feat(seedbox): autoclean torlink records whose files are gone#148
ralyodio merged 1 commit into
masterfrom
feat/seedbox-autoclean

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

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:

torlink reports : 63 torrents
on disk         : 39 directories
ghosts          : 40 paused records for data that no longer exists

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:

Remove 40 stale record(s) · Forgets the record only; no files are deleted.

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:

Guard Rationale
Always remove, never delete delete unlinks files; remove only forgets. A bug in the staleness check cannot destroy data.
Refuses to prune if the disk listing is unreadable "not on disk" would really mean "couldn't look".
Refuses to prune if the disk listing is empty Indistinguishable from a file server pointed at the wrong directory — pruning against it would erase every record on the box.
Only seeding / paused / torlink's own missing downloading, queued, failed and unrecognised states have no files yet and are never pruned.
Autoclean runs once per mount The poll re-renders every few seconds; otherwise it'd fire an endless stream of control calls.
Control calls are sequential This daemon is already known to wedge. A tidy-up must not become an outage.
404 from torlink counts as success Already gone is the desired end state, not an error worth showing.

Also

Deduplicates listOnDiskNames, which the status route and cleanup both needed, into files.ts beside 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. Plus isStaleTorrent in torlink-reconcile.ts.

Full suite: 181 files, 2494 passed, clean tsc --noEmit.

Two react-hooks/set-state-in-effect warnings (not errors) remain in torlink-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

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>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit 59cc993 into master Jul 31, 2026
8 checks passed
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.

1 participant