Steps 7 and 8: torrents, OPML, and polish
librqbit replaces the vendored BitTorrent 4.2.1 tree. Torrents download in place because seeding serves the files it downloaded, so the planned stage-then-move would have broken it. The stall budget now also covers magnet metadata resolution, which otherwise never returns against a dead swarm and wedged the scan. Adds add/rm/import/export, tracing setup, systemd units and README. A successful swarm download is unverified: no reachable peers here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPyeapneuXrCdojsaiXGbe
This commit is contained in:
53
PROGRESS.md
53
PROGRESS.md
@@ -13,8 +13,9 @@ The full design and step list live in the plan file at
|
||||
- [x] **4. `download.rs`** — downloads, filters, dedupe.
|
||||
- [x] **5. `retention.rs`** — oldest-first quota + age reaper.
|
||||
- [x] **6. `ipc.rs` + daemon** — UDS JSON-lines server, TTL scheduler, CLI-proxies-to-daemon.
|
||||
- [ ] **7. `torrent.rs`** — librqbit, seed to ratio/time, stall abort. *Done when:* smoke 5 passes.
|
||||
- [ ] **8. OPML + polish** — import/export, add/rm/status, tracing setup, systemd unit, README.
|
||||
- [x] **7. `torrent.rs`** — librqbit, seed to ratio/time, stall abort. (swarm download unverified —
|
||||
see the step 7 entry)
|
||||
- [x] **8. OPML + polish** — import/export, add/rm/status, tracing setup, systemd units, README.
|
||||
|
||||
## Smoke tests
|
||||
|
||||
@@ -29,6 +30,54 @@ The full design and step list live in the plan file at
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-09 — Step 8: OPML and polish
|
||||
|
||||
`ipx add <url>` fetches the feed to name it from its own title (`Accidental Tech Podcast` ->
|
||||
`accidental-tech-podcast`); a feed that cannot be reached is still added, named from its URL, rather
|
||||
than refused. `ipx rm` leaves downloads and history alone, so re-adding a feed does not re-pull its
|
||||
back catalogue. `ipx import`/`export` walk nested OPML folder outlines and skip URLs already
|
||||
subscribed. `tracing` logs to stderr, `IPX_LOG` sets the filter. `contrib/` has a systemd user unit
|
||||
for the daemon, plus a timer and one-shot service for the no-daemon style (with the caveat that
|
||||
without a daemon there is no socket for a UI).
|
||||
|
||||
Verified: `cargo test` 27/27. Round-trip — exported 3 feeds with real titles, removed one,
|
||||
re-imported: exactly the missing one came back, no duplicates, config still mode 0600. Quickstart
|
||||
from a genuinely empty home with no env overrides: `list` on a missing config, `add`, `fetch`
|
||||
(1 downloaded, 1 explicit skipped, 1 torrent 404), `list`; every path resolved under `$HOME`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-09 — Step 7: torrent.rs
|
||||
|
||||
`src/torrent.rs`: a librqbit `Session` started lazily on first torrent (binding ports and starting a
|
||||
DHT for a config that has never seen a torrent would be rude). `.torrent` URLs and magnets both go
|
||||
through `AddTorrent::from_url`. Progress is polled once a second and reported through the same
|
||||
`Progress` events HTTP downloads use.
|
||||
|
||||
Downloads go **straight into the feed folder** rather than staging and moving. The plan said move
|
||||
then seed, which cannot work — seeding serves the files it downloaded, so moving them first breaks
|
||||
it. In-place also removes a copy the original had to do.
|
||||
|
||||
Seeding stops at `seed_ratio` or `seed_time_mins`, whichever comes first, then the torrent is
|
||||
released from the session (files kept).
|
||||
|
||||
**Bug the smoke test caught:** the stall budget only covered the download loop, but resolving a
|
||||
magnet's metadata happens inside `add_torrent`, which against a dead swarm never returns — a
|
||||
torrent nobody seeds wedged the scan indefinitely. `add_torrent` is now wrapped in the same budget.
|
||||
|
||||
Verified: `cargo test` 27/27 (ratio incl. the divide-by-zero case, stall_mins = 0 not meaning
|
||||
"abort instantly"). Routing: with `enabled = false` a torrent enclosure is marked
|
||||
`skipped/torrents disabled` and never attempted. Session startup works here. Stall abort measured
|
||||
end to end: with `stall_mins = 1`, a dead magnet failed at 20:58:23 -> 20:59:24, exactly 61s, and
|
||||
the row recorded `error / no metadata after 1 minutes, gave up`.
|
||||
|
||||
**Not verified: an actual successful swarm download.** This sandbox has no reachable peers, so
|
||||
smoke 5's happy path — payload lands, seeding stops at the ratio — has not been run. The code paths
|
||||
either side of it are tested; the swarm itself needs a real network. Worth running once against a
|
||||
live torrent feed before trusting it.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-09 — Step 6: ipc.rs + daemon
|
||||
|
||||
`src/ipc.rs`: `Event` and `Command` as serde-tagged enums (`{"ev":...}` / `{"cmd":...}`), one JSON
|
||||
|
||||
Reference in New Issue
Block a user