deps: migrate ergasia to librqbit 9 - #735
Merged
Merged
Conversation
added 5 commits
August 25, 2026 19:03
librqbit 9 restructured SessionOptions. The reported errors named the DHT fields, but four more shapes moved in the same struct and would have surfaced one compile at a time: listen_port_range and enable_upnp_port_forwarding are gone, peer_opts moved under a connect block, and TorrentStatsState::Initializing became a struct variant carrying `paused`, which breaks two match sites the error list never mentioned. Every shape here was read from the crate source at tag v9.0.1 rather than inferred from the error text. Two behaviours needed deliberate work to survive the bump. v8 hardcoded 0.0.0.0 for both the TCP listener and the DHT socket. v9 defaults to dual-stack [::]. ipv4_only is therefore set explicitly at both levels, so this bump does not silently change what the torrent session binds. Going dual-stack is a real v9 feature and worth taking deliberately -- a dependency bump is the wrong place to opt into it. v9 also dropped the listener's port-range scan, taking a single listen_addr with no retry. The old behaviour is reproduced by retrying Session::new_with_opts per candidate port. The listener bind is the first fallible step in that call, so a failed attempt leaves nothing to unwind. Probing a bind, dropping it, and handing librqbit a bare port would have introduced a TOCTOU window that v8 never had. A doc citation pointing at librqbit-8.1.1 session.rs is repointed at the 9.0.1 lines; the tier logic it cites is unchanged between versions, only moved. Closes #724
Six more breaks, five reported by CI and one found by sweeping for the same
shapes -- the gate aborts at the first failing crate, so its list is what
compiled up to the abort rather than what is broken.
TorrentMetadata dropped its cached `name` field; the name now comes from
`info.name()`, an encoding-aware decode. Used librqbit's own idiom from
ManagedTorrent::name rather than inventing a conversion, which also preserves
the Option<String> the caller already expects.
create_torrent takes a BlockingSpawner explicitly in v9, where v8 built one
internally, and v9's BlockingSpawner has no Default. Traced what the spawner is
actually used for before choosing a value: the semaphore is acquired once per
call and the only dispatched work is block_in_place, gated by runtime flavor --
so capacity is inert for a spawner nothing else shares, and `new(1)` matches an
existing in-crate precedent for the same one-off case. The third site was in
archon rather than ergasia and would have failed on the next run.
The remaining two are the Initializing struct-variant change at a site that
CONSTRUCTS the value rather than matching it, so `{ .. }` does not apply. The
tuple's neighbouring bool is `finished`, a different concept from the new
`paused`, so nothing is double-encoded; the consuming match ignores `paused`
unconditionally.
Swept the workspace for every migrated type and for bare Initializing, including
separate integration-test targets: only ergasia and archon depend on librqbit,
and nothing else references these shapes.
…v9's dual-stack bind CI's test failure traced to a mechanism the assertion did not suggest. librqbit 9 pulls rustls with aws-lc-rs while this workspace declares it with ring; cargo features are additive across a build, so both providers end up active and rustls's auto-select refuses to choose. The panic surfaced as an unrelated lifecycle test failing, because a renderer task that panics makes JoinHandle::is_finished true immediately and the op slot reaps it early. Three call sites used the ambiguous builder. archon's render/tls.rs was the one CI reached; two more in syndesis would have failed next. All now request ring explicitly, matching what those files already do elsewhere. quinn-proto's own helper was unaffected because it already asks for a provider by name. progress.rs drops a conversion that librqbit 9 made a no-op: the peer-stats `live` field narrowed from usize to u32 upstream, so the fallible narrowing has nothing left to narrow. The session now binds dual-stack, taking librqbit 9's own default rather than pinning back to v8's IPv4-only behaviour. That is a deliberate choice rather than a side effect: `ipv4_only` is left unset at both the session and listener level, so the TCP listener, the DHT socket and the outbound connector all follow v9. The RUSTSEC-2025-0012 exception for `backoff` goes with it -- librqbit 9 replaced that dependency with `backon`, so the advisory no longer reaches this graph.
…three dead advisories librqbit 9 widens the graph and cargo-deny's multiple-versions rule refuses it. Three duplicates, and only one is genuinely ours to exempt. atoi is upstream-blocked in both directions: sqlx-sqlite's newest release still pins 2.0 and librqbit 9 pins 3. cargo update cannot close a gap where both sides are already newest and disagree on a major, so it is skipped with the specific crates and versions named. reqwest is deliberately NOT skipped. Our own manifest caps us below 0.13, and lifting that cap is #731's core change -- so this unifies by sequencing rather than by exemption. wasm-streams is purely downstream of reqwest and needs no action of its own. Three advisory exceptions are dead and removed. bincode is entirely absent from this branch's lock where main carried two versions, so RUSTSEC-2025-0141 and its two skip entries go. Checking that turned up the same shape in quick-xml: main had two versions, this branch has one because librqbit-upnp no longer pins the old range, so RUSTSEC-2026-0194 and -0195 go with it. A comment on an unrelated syn entry that referred back to bincode is corrected rather than left dangling. The derived ignore files are regenerated through the tool their own header names as the source of truth, not hand-edited, and check clean against deny.toml.
Rebased onto #731. The prediction it carried holds: with archon on reqwest 0.13 and librqbit 9 resolving to 0.13.4, the two converge -- the lock now has ONE reqwest entry and wasm-streams 0.4.2 drops out entirely. So #731's temporary skips are removed rather than duplicated here, which is what its own comment asked for: one exemption, removed once, not two. bincode goes with them; it is absent from this lock, since librqbit 9 no longer pulls the 1.x line. atoi stays, and it is the only duplicate genuinely exempted: sqlx-sqlite pins 2.0 at its newest release and librqbit 9 pins 3, so no cargo update closes it. The rustls provider fix is not re-applied -- #731 landed the same change in archon and syndesis, and this branch takes main's version of both files. The lock is regenerated by cargo rather than hand-merged through the rebase conflict. Each side had resolved with the other's crate still present, so combining them by hand would have produced a file cargo would not.
forkwright
force-pushed
the
chore/librqbit-9-migrate
branch
from
August 26, 2026 00:05
a6aa4f7 to
235c1fc
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.
Finding
librqbit 9 restructured
SessionOptions. The dependabot PR's error list named the DHT fields; four more shapes moved in the same struct and would otherwise have surfaced one compile at a time.Every API shape below was read from the crate source at tag
v9.0.1(ikatson/rqbit@a499d2f2), never inferred from the error text.disable_dht/disable_dht_persistence/dht_config: Option<PersistentDhtConfig>dht: Option<DhtSessionConfig>(session.rs:418-421);PersistentDhtConfigrenamedDhtPersistenceConfiglisten_port_range: Option<Range<u16>>,enable_upnp_port_forwardinglisten: Option<ListenerOptions>with a singlelisten_addr— the port-scan loop is gonepeer_optsonSessionOptionsconnect: Option<ConnectionOptions>Session::tcp_listen_port()Session::announce_port()TorrentStatsState::Initializing(unit)Initializing { paused: bool }(struct) — broke twomatchsites not in the error listTwo behaviours needed deliberate work to survive the bump
IPv4-only bind — v9 silently changes this. v8 hardcoded
0.0.0.0for both the TCP listener and the DHT socket (verified increate_tcp_listenerandDhtState::with_config'sNonefallback). v9 defaults to dual-stack[::]unlessipv4_onlyis set.ipv4_only: trueis therefore set at both the top-levelSessionOptions(governing the DHT bind and outbound connector) and the nestedListenerOptions(governing the TCP listener), reproducing v8 exactly.Going dual-stack is a real, deliberate v9 feature and may well be what we want — but a dependency-bump PR is the wrong place to opt into it silently. Flagged here and in
docs/download/torrent.mdfor a separate decision.Port-range scan. v9 removed the range scan entirely. The old "try each port, bind the first that works" behaviour is reproduced by retrying
Session::new_with_optsper candidate port. The listener bind is the first fallible step in that call — confirmed by reading the construction order — so a failed attempt leaves nothing to unwind, making this equivalent to v8's loop rather than a new race.The alternative (probe-bind, drop, hand librqbit a bare port) was deliberately avoided: it introduces a TOCTOU window that v8 never had.
Lockfile
Regenerated by
cargo update -p librqbit --precise 9.0.1rather than hand-edited.Flagged, not fixed
deny.toml/osv-scanner.tomlcarry an exception forRUSTSEC-2025-0012("backoff unmaintained — transitive via librqbit"). librqbit 9 replacedbackoffwithbackon, so that exception may now be dead weight. Left alone: the real graph only exists once the lock resolves, and writing a justification against a guessed graph is how a wrong one gets recorded. Worth acargo deny checkpass on this branch.Closes #724.