Repository navigation
feat(engine): on-complete hook, queueing, share ratio, disk-space guard, .part files (WI-1730) - #108
Merged
Merged
Conversation
… guard, .part Adds the engine side of WI-1730 (rustTorrent WP5, polish review H6 and parity items) in the session and torrent modules. CLI flags, compat endpoints and the policy settings UI are wired in other packages. - On-complete hook: optional shell command (RTBIT_* env) and/or a JSON webhook POST, run detached when a torrent finishes downloading. Torrents already complete on initialize (session restore) do not fire it. Configure with Session::set_on_complete_hook. - Queueing: Session::set_max_active_downloads / set_max_active_seeds. A periodic policy pass keeps the oldest torrents running and parks the rest in a queue (Torrent::is_queued). User pause/resume overrides it. - Share limits: Session::set_share_limits with a ratio and/or seeding time. Reaching either pauses a seeding torrent. Counters are per process, not persisted. - Low-disk guard: Session::set_min_free_disk_space holds downloads when free space falls below the threshold and resumes them at twice the threshold, so they do not flap. - .part files: Session::set_use_part_files writes incomplete files as <name>.part and renames each to its final name when it completes. An existing final name is always used. Applies to torrents added later. Pure decision functions (queue plan, share limit, disk hysteresis) and the storage rename paths have unit tests. The policy pass itself is not covered by an integration test. Refs WI-1730 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…starts The policy pass pauses torrents for three reasons: queue slot, low disk space, and share limit. Those reasons lived only in memory, so a restart brought every such torrent back paused with no flag set. The policy pass never resumes an unflagged paused torrent, so queued and disk-held downloads stayed paused forever after a restart. - Add a share_paused flag beside queued and held_for_disk. - Replace the policy_pause(queued, held) bool pair with a PolicyPause reason that sets exactly one flag, and read/write all three through PolicyFlags. - Persist the three flags in the JSON and Postgres session stores. The Postgres columns are added with defaults, so existing databases migrate in place and older state files still load. - On restore, reapply the flags once each torrent is added back. - Add session-level tests that drive policy_pass() directly: queue limit and release, queued download across restart, disk hold across restart, and share-paused seed across restart. Refs WI-1730 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
update_db read the torrent's paused and policy flags before taking the database lock. Two concurrent updates could therefore store in the reverse order of their reads, and the older snapshot would win. The share-paused restart test hit this about once in 25 runs: the file recorded a paused torrent without its share-limit flag. Read the torrent and insert it under one lock. flush() takes the same lock, so it runs after the guard is released. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…ime out on-complete command - Share limits (ratio and seeding time) and the upload total are saved with each torrent in the JSON and Postgres session stores. The upload total is kept in a base counter that a pause folds the live run into, so it accumulates across pauses and restarts. Restore reapplies both, so a limit that has not yet tripped still trips after a restart. - session.stop() persists each torrent before pausing it, so a clean restart keeps the upload total and each torrent's running state. - A torrent's .part choice is saved and reapplied on restore. An existing <name>.part file is adopted whatever the session setting says, so a partial download is not orphaned and redownloaded. - The on-complete command runs as a tokio child with kill_on_drop and a 5 minute timeout, so a hung script cannot hold a blocking thread. - AddTorrentOptions::part_files (Option, default: session setting) lets a caller pin the choice per torrent. Restart tests cover share limits and uploads (including a restored ratio limit that trips after uploads continue), the persisted .part choice with the switch off, and adoption of an existing .part file. A unit test covers the command timeout. Refs WI-1730 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…are_limits Upload totals and share limits were only saved on pause and on a clean stop, and the binary never called stop(), so a SIGINT/SIGTERM restart lost them. - Session::persist_all saves every torrent. stop() uses it before pausing. - A persist timer saves every torrent each persist_interval (new SessionOptions field, default 60 s), so a kill loses at most that much. - The rtbit server path calls session.stop() after the HTTP API returns on cancel, so SIGINT and SIGTERM save before the process exits. - Session::set_share_limits is async and saves the torrent right away. Tests: a drop without a final save keeps the upload total (saved by the timer) and the share limits (saved by set_share_limits). The session is killed by cancelling its token, which ends its tasks with no final save. Refs WI-1730 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
thedancingdeveloper
force-pushed
the
wi-1730-engine-parity
branch
from
October 17, 2026 10:49
151a926 to
b71f960
Compare
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.
WP5 engine feature parity (WI-1730, polish review PR #94).
.partnames for incomplete files; an existing.partis adopted, and the file is renamed when it completes.partchoicesession.stop()(the rtbit server now calls it on SIGINT/SIGTERM), on a 60 s timer, and straight away inset_share_limitsGates at 151a926: fmt ok;
cargo test -p swarmforge --lib159 passed / 5 ignored;cargo check --workspace --all-targetsand the postgres feature check pass.Not yet covered: the signal path has no test, Postgres has not been run against a live database, and the CLI flags and compat endpoints are not wired yet.
🤖 Generated with Claude Code