chore: initial sanitized public snapshot

This commit is contained in:
Aria2 Rust Pro Contributors
2026-07-18 15:24:15 +08:00
commit e489b29e01
321 changed files with 76890 additions and 0 deletions
@@ -0,0 +1,19 @@
# ADR 0001: Rust-Native Rewrite
## Decision
`aria2-rust-pro` is a Rust-native rewrite of the current C++ Pro Core behavior.
It does not wrap the C++ implementation and does not reuse the deleted previous
Rust rewrite.
## Rationale
The project needs a maintainable Rust 2024 codebase with strict testing and
Cargo-native quality gates while preserving external aria2 compatibility.
## Consequences
- Compatibility must be proven through golden outputs and behavior tests.
- Missing behavior must be tracked in `progress.md` and the compatibility
ledger.
- `unsafe` is forbidden unless a later ADR narrowly approves it.
+103
View File
@@ -0,0 +1,103 @@
# aria2 Compatibility Ledger
Status values:
- `planned`: required but not implemented.
- `implemented`: implementation exists but is not fully verified.
- `verified`: behavior is covered by tests or golden evidence.
- `deferred`: intentionally delayed with a recorded reason.
- `approved-incompatible`: explicitly approved incompatibility.
No row may remain `planned` for the 1.0 release.
## Public Surfaces
| Surface | Target | Status | Evidence |
| --- | --- | --- | --- |
| CLI executable | aria2-compatible command behavior | verified | `crates/aria2-rust-pro-cli/src/lib.rs` now exposes startup profile, command surface, config validation, runtime report models, aria2-shaped `--version` / `--help=#all` rendering, and real filtered `--help=<tag|keyword>` output while `docs/compatibility/goldens/cli/` captures the current release-binary output for both `--version` and `--help=#all`; `crates/aria2-rust-pro-compat/src/help.rs` has direct tests for the aria2-style version banner, full help, and filtered help |
| CLI options | original aria2 plus current Pro options | verified | normalized option registry in `crates/aria2-rust-pro-compat/src/options.rs` now exposes registry-backed CLI/config/RPC spelling helpers (`cli_spellings`, `config_spellings`, `lookup_spellings`), help placeholders, help synopsis generation, and a `live_option_specs()` view of the implemented surface, while `crates/aria2-rust-pro-cli/src/lib.rs` now directly proves long-form compat alias canonicalization (`http-want-digest` -> `no-want-digest-header`), bool/value option parsing, and representative live option preservation through `parse_cli()` |
| Config file | aria2 config syntax | verified | `crates/aria2-rust-pro-compat/src/config.rs` now directly covers config AST/document/profile/normalization, BOM handling, long-form and short-form compatibility alias canonicalization, strict unknown-option rejection, and normalized profile loading, while `crates/aria2-rust-pro-cli/src/lib.rs` proves file-backed config loading plus CLI-over-config precedence for representative runtime/session/transport options |
| JSON-RPC | aria2 JSON-RPC methods and fields | verified | method ledger plus `dispatcher/router/handlers/jsonrpc` module tree in `crates/aria2-rust-pro-rpc/src/` now have direct evidence for batch handling, routed id preservation, invalid-request/invalid-param shaping, success-payload rendering, effective default-plus-inherited option views, upstream-style per-download GID/state errors, transport-visible HTTP/WebSocket behavior, and JSON/XML parity across the covered method surface; `crates/aria2-rust-pro-rpc/src/dispatcher.rs` now additionally proves a raw JSON-RPC success request can parse, dispatch, and render a transport-visible success payload without leaking an `error` member |
| XML-RPC | original aria2 XML-RPC compatibility | verified | `crates/aria2-rust-pro-rpc/src/xmlrpc.rs` now has request/response/value/fault models, shared XML-RPC-to-RPC conversion, deterministic XML rendering helpers, and XML parsers for methodCall/methodResponse/fault; typed scalar parsing now also tolerates whitespace-padded `int` / `i4` / `i8` / `biginteger` / `boolean` / `double` / `dateTime.iso8601` / `base64` tags without regressing the earlier large-integer fallback behavior; `crates/aria2-rust-pro-rpc/src/dispatcher.rs` now routes ordinary XML-RPC methods through the real in-process dispatcher instead of stub handlers, so XML-RPC `tellStatus`, `getGlobalStat`, and other non-multicall methods reuse the same payload semantics as JSON-RPC; top-level XML-RPC faults now use upstream-style `faultCode=1` / `faultString`, XML-RPC `system.multicall` now emits upstream-style in-band fault structs instead of JSON-style `code` / `message` members, `crates/aria2-rust-pro-rpc/src/server.rs` now recognizes obvious XML-RPC `methodCall` bodies on normalized `/rpc` paths even when the client omits a helpful `Content-Type` and prefixes the payload with a BOM/comment prelude, and `crates/aria2-rust-pro-tests/src/lib.rs` now proves XML-RPC `methodCall` parse/render can drive `aria2.addMetalink` dispatch while still converging on the protocol-layer preferred resource candidate |
| Session files | aria2 session/input conventions | verified | `crates/aria2-rust-pro-storage/src/session.rs` session file and metadata state shell now has explicit coverage for mixed legacy/v2 session lines, multiple URIs, and escaped metadata while still preserving conservative resume/runtime extension keys via metadata maps; `crates/aria2-rust-pro-tests/src/lib.rs` now proves JSON-RPC `saveSession` output is readable by storage session loading, and `crates/aria2-rust-pro-core/src/engine.rs` now round-trips multi-URI downloads through session save/load without collapsing to one URI |
| Control files | `.aria2` resume behavior | verified | `crates/aria2-rust-pro-storage/src/control.rs` now auto-detects upstream binary `.aria2` files, reads both the legacy v0000 little-endian and v0001 network-order headers, reconstructs verified/in-flight piece state from the upstream bitfields, and writes an upstream-readable binary prefix plus a Rust trailer that preserves richer metadata such as retry counts and last-error state; the same file now carries fixture-backed binary-reader tests plus core session/control recovery coverage |
| HTTP/HTTPS | range, resume, retry, checksum | verified | `crates/aria2-rust-pro-protocol/src/http.rs` now computes inline-payload checksum verification in `completion_model()`, carries streamed observed-length/digest truth, models unsatisfied `Content-Range` responses for `416 Range Not Satisfiable`, and preserves clearer resume truth when a server ignores a requested range; `crates/aria2-rust-pro-protocol/src/downloader.rs` directly covers fixture/downloader-generated streamed responses, request-proxy routing with bypass rules, finer DNS/TLS/proxy failure mapping, fixture/live `416` parsing, live query emission, redirect-origin provenance, and negotiated HTTP version mapping; `crates/aria2-rust-pro-cli/src/lib.rs` and `crates/aria2-rust-pro-tests/src/lib.rs` together cover partial-range completion, retry, checksum-aware completion, and connector-backed runtime execution across the current HTTP/HTTPS surface |
| FTP | original aria2 FTP behavior | verified | `crates/aria2-rust-pro-protocol/src/ftp.rs` FTP model plus fixture-backed downloader support in `crates/aria2-rust-pro-protocol/src/downloader.rs`, CLI runtime execution wiring in `crates/aria2-rust-pro-cli/src/lib.rs`, and a local real FTP server smoke in CLI tests that exercises USER/PASS/PASV/RETR over real sockets |
| SFTP | original aria2 SFTP behavior | verified | `crates/aria2-rust-pro-protocol/src/sftp.rs` SFTP model plus fixture-backed downloader support in `crates/aria2-rust-pro-protocol/src/downloader.rs`, CLI runtime execution wiring in `crates/aria2-rust-pro-cli/src/lib.rs`, and a local live SFTP smoke using a Docker loopback server |
| Metalink | Metalink3/4 compatibility | verified | `crates/aria2-rust-pro-protocol/src/metalink.rs` now has a structured XML parser, preferred-resource selection helpers, and a shared multi-file download-plan surface, separates document-level `<identity>` from file-level `<identity>`, preserves CDATA-backed `<signature>` / `<url>` payloads, normalizes checksum algorithms/values plus resource `location` / `lang` / `type` / `private` metadata, ignores piece-level hashes for file verification, and uses richer preferred-resource tie-breaking; `crates/aria2-rust-pro-cli/src/lib.rs` now resolves both local `.meta4` / `.metalink` files and remote HTTP/HTTPS Metalink documents through that shared plan before downloading every actionable file while injecting implied per-file `out` / `checksum` defaults into execution, `crates/aria2-rust-pro-rpc/src/dispatcher.rs` uses the same plan for `aria2.addMetalink` and returns one GID per actionable file, `crates/aria2-rust-pro-protocol/src/bt_metalink.rs` now delegates wrapper parsing to the real parser instead of returning a root-only stub document while preserving that richer normalized model, and `crates/aria2-rust-pro-tests/src/lib.rs` exercises both JSON-RPC and XML-RPC entrypoints for the same multi-file expansion semantics while CLI tests cover local and remote Metalink document execution |
| BitTorrent | torrent, magnet, DHT, tracker, seeding | verified | `crates/aria2-rust-pro-protocol/src/magnet.rs`, `torrent.rs`, `tracker.rs`, `transport.rs`, and `bt_metalink.rs` directly cover magnet parsing/serialization, torrent metadata/info-hash extraction, tracker announce/scrape parsing plus live HTTP tracker transport, UDP tracker codecs, peer-wire codecs, and typed DHT helpers; `crates/aria2-rust-pro-rpc/src/dispatcher.rs` now directly proves `.torrent` and magnet registration, tracker announce/scrape ingestion, peer-wire exchange, `ping` / `find_node` / `get_peers` / `announce_peer` runtime updates, `select-file`, BT share/seeding visibility, and metadata-only magnet promotion through BEP10/BEP9 `ut_metadata` negotiation into the same torrent-backed runtime surface used by `.torrent` bootstrap; `crates/aria2-rust-pro-cli/src/lib.rs` and `crates/aria2-rust-pro-tests/src/lib.rs` provide CLI-visible BT status/share snapshots, false-completion/select-file contracts, pressure smokes, mixed magnet/torrent status/getServers coverage, and the dedicated `bt_magnet_promotion` regression that locks the promotion path at the public surface |
| Docker env | current Pro Docker compatibility | verified | `docker/Dockerfile`, `docker/entrypoint.sh`, `docker/docker-compose.yml`, `docker/.env.example`, `xtask docker smoke`, and `xtask docker smoke-local` now provide a source-building container path with verified daemon-free and daemon-backed smokes; `scripts/docker/smoke.ps1` and `scripts/docker/smoke-local.ps1` are compatibility wrappers around those Cargo-native commands; the entrypoint now maps the legacy env names (`PUID`, `PGID`, `UMASK_SET`, `RPC_SECRET`, `RPC_PORT`, `LISTEN_PORT`, `DISK_CACHE`, `IPV6_MODE`, `UPDATE_TRACKERS`, `CUSTOM_TRACKER_URL`, `SPECIAL_MODE`) into the generated runtime config and bundled hook/tracker behavior, including seeded `bt-tracker`, tracker updates, and `move` / `rclone` completion hooks |
Compatibility relock note: `crates/aria2-rust-pro-core/src/engine.rs` now rejects invalid `pause`/`unpause` state transitions instead of silently accepting them, and `crates/aria2-rust-pro-rpc/src/dispatcher.rs` now has targeted tests proving upstream-style `cannot be paused now` / `cannot be unpaused now` errors for real invalid states as well as missing GIDs.
Compatibility relock note: public JSON-RPC methods that take a GID from param 0 now distinguish missing params from malformed GIDs, returning upstream-style `Invalid GID ...` application errors for bad hex input instead of collapsing those cases into `invalid_params` or `unknown_method`.
Compatibility relock note: the invalid-GID regression matrix now explicitly covers `tellStatus`, `getOption`, `changeOption`, `getUris`, `getFiles`, `changeUri`, `changePosition`, `pause`, `unpause`, `remove`, and `removeDownloadResult`, so the shared dispatcher helper change is backed by method-level evidence instead of only a subset of entrypoints.
Compatibility relock note: `aria2.changePosition` failures now use the upstream waiting-queue-specific wording `GID#... not found in the waiting queue.` instead of the earlier generic local `Could not change position...` message.
Compatibility relock note: the BT/tracker/DHT helper entrypoints in `dispatcher.rs` now follow the same GID semantics as the public RPC layer, using `Invalid GID ...` for malformed hex and `No such download for GID#...` when the referenced download does not exist, instead of leaking `unknown_method`.
Compatibility relock note: `aria2.changeUri` now matches the upstream mixed-array parsing behavior more closely by silently skipping non-string `delUris` / `addUris` entries while still applying delete-then-insert semantics to string members, and it now has explicit coverage for the upstream-style valid-but-missing-GID error `Cannot remove URIs from GID#...`.
Compatibility relock note: across the currently covered per-download and BT helper paths, the repo now distinguishes the upstream-style failure buckets for missing params, malformed GIDs, nonexistent downloads, invalid `pause` / `unpause` states, waiting-queue misses, and valid-but-missing `changeUri` removals instead of collapsing them into generic local dispatcher errors.
Compatibility relock note: the JSON-RPC transport now preserves broader upstream-style request-id shapes, including boolean and structured ids, treats malformed request shapes as synthetic invalid-request / invalid-params dispatches instead of transport parse aborts, and ignores non-object batch members while keeping shared JSON/XML error shaping aligned through `model.rs`, `router.rs`, `handlers.rs`, and `jsonrpc.rs`.
Compatibility relock note: the XML-RPC surface now accepts a wider set of real-client request forms, including processing instructions, comments, whitespace-tolerant self-closing tags, empty value/container forms, `nil`, and decimal/hex numeric entities, while preserving shared fault semantics and avoiding lossy large-number truncation on RPC-to-XML rendering.
Compatibility relock note: `crates/aria2-rust-pro-core/src/request.rs` now normalizes multi-URI request invariants by filtering empty URI entries, de-duplicating/repositioning repeated URIs, and repairing stale primary URI state at `RequestGroup::with_context`, reducing drift between `changeUri`, `getUris`, and session replay paths.
## Option Ledger
| Option | Source | Required behavior | Status | Evidence |
| --- | --- | --- | --- | --- |
| `dir` | Original | local file output directory option | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_DIR`) |
| `out` | Original | per-download output filename option | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_OUT`) |
| `split` | Original | split count option (default `5`) | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_SPLIT`) |
| `continue` | Original | resume partial download (`-c`) | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_CONTINUE`) |
| `enable-rpc` | Original | enable JSON-RPC/XML-RPC server | verified | `aria2/src/OptionHandlerFactory.cc`, `aria2/src/usage_text.h` |
| `rpc-listen-port` | Original | RPC listen port (default `6800`) | verified | `aria2/src/OptionHandlerFactory.cc`, `aria2/src/usage_text.h` |
| `listen-port` | Original | BT TCP/UDP listen port | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs`, `crates/aria2-rust-pro-cli/src/lib.rs`, `docker/entrypoint.sh`, `xtask docker smoke-local` |
| `dht-listen-port` | Original | DHT UDP listen port | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs`, `crates/aria2-rust-pro-cli/src/lib.rs`, `docker/entrypoint.sh`, `xtask docker smoke-local` |
| `disable-ipv6` | Original | disable IPv6 sockets and resolution | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs`, `crates/aria2-rust-pro-cli/src/lib.rs`, `docker/entrypoint.sh`, `xtask docker smoke-local` |
| `bt-save-metadata` | Original | save bt metadata during magnet flow | verified | `aria2/src/OptionHandlerFactory.cc`, `aria2/src/usage_text.h` |
| `follow-torrent` | Original | control how torrent/metalink references are followed | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_FOLLOW_TORRENT`) |
| `metalink-enable-unique-protocol` | Original | enforce unique protocol in metalink handling | verified | `aria2/src/OptionHandlerFactory.cc` (`PREF_METALINK_ENABLE_UNIQUE_PROTOCOL`) |
| `max-connection-per-server` | Pro | no 16-connection cap | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry |
| `split` | Original | per-download split count participates in HTTP connection budgeting and bounded follow-up range planning | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` plus runtime/task integration in `crates/aria2-rust-pro-cli/src/lib.rs` |
| `min-split-size` | Pro | minimum `1K` target in later phase behavior | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `piece-length` | Pro | minimum `1K` target in later phase behavior | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `retry-on-400` | Pro | retry only when enabled and `retry-wait > 0` | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `retry-on-403` | Pro | retry only when enabled and `retry-wait > 0` | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `retry-on-406` | Pro | retry only when enabled and `retry-wait > 0` | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `retry-on-unknown` | Pro | retry only when enabled and `retry-wait > 0` | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` option registry target |
| `no-want-digest-header` | Pro | canonical option for digest header behavior | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` alias-aware registry |
| `http-want-digest` | CompatibilityAlias | compatibility alias mapped to `no-want-digest-header` | implemented | `crates/aria2-rust-pro-compat/src/options/mod.rs` alias-aware registry |
## Current Coverage
| Area | Status | Evidence |
| --- | --- | --- |
| Core download/task model | implemented | `crates/aria2-rust-pro-core/src/engine.rs`, `request.rs`, `progress.rs`, `session.rs`, `scheduler.rs`; current Phase 3 core now carries concrete segment assignments in `RequestGroup` and scheduler-built byte ranges in `schedule_once()` |
| HTTP/HTTPS protocol surface | implemented | `crates/aria2-rust-pro-protocol/src/http.rs`, `downloader.rs`, `transport.rs`, `auth.rs` |
| FTP/SFTP fallback | implemented | `crates/aria2-rust-pro-protocol/src/ftp.rs` and `sftp.rs` model shells, plus fixture-backed downloader execution in `crates/aria2-rust-pro-protocol/src/downloader.rs` and runtime dispatch in `crates/aria2-rust-pro-cli/src/lib.rs` |
| Magnet parsing | implemented | `crates/aria2-rust-pro-protocol/src/magnet.rs` now has magnet URI parsing/serialization helpers and tests, while `bt_metalink.rs` keeps the compatibility wrapper aligned with the shared parser |
| Metalink parser facade | implemented | `crates/aria2-rust-pro-protocol/src/metalink.rs` now parses file/resource/checksum XML structure and exposes deterministic preferred-resource / first-actionable-candidate helpers, while `bt_metalink.rs` still provides compatibility bridge helpers |
| Torrent parser facade | implemented | `crates/aria2-rust-pro-protocol/src/torrent.rs` now parses torrent bencode metadata, derives raw-info SHA1 hashes, materializes file/piece/tracker models, builds tracker request metadata, and carries peer-wire handshake/message parse-serialize helpers; `crates/aria2-rust-pro-protocol/src/tracker.rs` now parses announce/scrape responses, builds encoded tracker URLs, and carries UDP tracker protocol helpers |
| RPC method ledger | implemented | `crates/aria2-rust-pro-rpc/src/methods.rs` |
| In-process RPC bridge | implemented | `crates/aria2-rust-pro-rpc/src/dispatcher.rs` and `handlers.rs` |
| Storage piece/control skeleton | implemented | `crates/aria2-rust-pro-storage/src/model.rs`, `control.rs`, `resume.rs`, `store.rs` |
| CLI-to-runtime bridge | implemented | `crates/aria2-rust-pro-cli/src/lib.rs` runtime/config/report bridge |
## Phase 3 HTTP Range/Resume/Retry Notes (In Progress)
| Topic | Current state | Status | Evidence | Next step |
| --- | --- | --- | --- | --- |
| Range request modeling | Range units/specs and request header surfaces are modeled | implemented | `crates/aria2-rust-pro-protocol/src/http.rs` (`RangeSpec`, `RangeUnit`, `HttpRequestModel`) | Bind modeled ranges to runtime piece/progress accounting for active transfers |
| Resume state persistence bridge | Session/control and resume model shells exist, including piece-state serialization surfaces, session metadata extension keys, request-level resume state, and control-file recovery of partial completed-length / retry-count state | implemented | `crates/aria2-rust-pro-storage/src/session.rs`, `crates/aria2-rust-pro-storage/src/control.rs`, `crates/aria2-rust-pro-storage/src/resume.rs`, `crates/aria2-rust-pro-core/src/request.rs`, `crates/aria2-rust-pro-core/src/engine.rs` | Extend from single-partial recovery into live segmented resume flows |
| Retry policy modeling | Retry policy/strategy types exist, runtime config carries retry toggles, aggregate retry counts surface through runtime/RPC state, and richer retry-attempt history is now retained across request/engine/RPC layers | implemented | `crates/aria2-rust-pro-protocol/src/http.rs` (`RetryPolicy`, `RetryStrategy`), `crates/aria2-rust-pro-core/src/request.rs`, `crates/aria2-rust-pro-core/src/runtime.rs`, `crates/aria2-rust-pro-rpc/src/dispatcher.rs` (`retryCount`, `retryAttempts`) | Persist richer retry-attempt history through more real session/control flows without overcommitting the public surface |
| Runtime transfer truth | Successful fixture HTTP transfers already feed length/completion/connection/retry-count state back into engine/RPC, control-file reload recovers partial progress when session metadata omits it, multi-step partial responses advance follow-up `Range` requests across segments, scheduler/session bridges now carry segment-plan, retry-history, active-segment counts, and concrete per-group segment assignments, `split` plus checksum-aware completion now constrain follow-up planning, and post-bootstrap core-planned follow-up ranges now run through a real concurrent segment executor rather than a serial CLI loop; inline payload checksum verification is real, storage now exposes observed byte sinks including a file-backed variant with explicit write-failure coverage, connector-returned inline bodies are normalized through the same sink before protocol/CLI/RPC consume it, and a live blocking HTTP connector can fetch local responses into sink-backed streamed results that runtime can complete against, but broader live-transport truth is still incomplete | implemented | `crates/aria2-rust-pro-storage/src/io.rs`, `crates/aria2-rust-pro-protocol/src/downloader.rs`, `crates/aria2-rust-pro-protocol/src/http.rs`, `crates/aria2-rust-pro-core/src/engine.rs`, `crates/aria2-rust-pro-core/src/request.rs`, `crates/aria2-rust-pro-core/src/scheduler.rs`, `crates/aria2-rust-pro-core/src/session.rs`, `crates/aria2-rust-pro-rpc/src/dispatcher.rs`, `crates/aria2-rust-pro-cli/src/lib.rs`, `crates/aria2-rust-pro-tests/src/lib.rs` | Extend beyond scripted fixture success paths into TLS-specific live coverage and deeper segment progress persistence through session/control/RPC |
| Binary `.aria2` compatibility | Upstream binary `.aria2` headers are auto-detected on read, decoded into current control metadata, and emitted again as the leading prefix when the metadata can be represented safely | verified | `crates/aria2-rust-pro-storage/src/control.rs` binary reader/writer plus fixture-backed tests for v0000/v0001 and round-trip recovery |
Compatibility note: this ledger records that HTTP range/resume/retry has strong type/model coverage and partial runtime wiring, but does not yet claim full aria2-equivalent runtime behavior until retry/partial-range/restart-coherence is validated end-to-end.
+28
View File
@@ -0,0 +1,28 @@
# CLI Golden Snapshots
This directory stores evidence-backed CLI compatibility snapshots captured from:
- upstream Windows aria2 `1.37.0`
- the current local `aria2-rust-pro` binary
The current capture script is:
- `xtask compat capture-cli-goldens`
- `scripts/compat/capture-cli-goldens.ps1` (thin compatibility shim)
It writes:
- `cli/upstream/version.txt`
- `cli/upstream/help-all.txt`
- `cli/rust/version.txt`
- `cli/rust/help-all.txt`
- `cli/manifest.json`
Run it from the repo root with:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- compat capture-cli-goldens
powershell -NoProfile -File .\scripts\compat\capture-cli-goldens.ps1
```
These files are evidence. They do not claim parity by themselves.
@@ -0,0 +1,9 @@
{
"generated_at_utc": "2026-05-27T02:54:18Z",
"captured": [
"upstream/version.txt",
"upstream/help-all.txt",
"rust/version.txt",
"rust/help-all.txt"
]
}
@@ -0,0 +1,220 @@
Usage: aria2c [OPTIONS] [URI | MAGNET | TORRENT_FILE | METALINK_FILE]...
Printing all options.
Options:
-v, --version Print the version number and exit.
Tags: #basic
-h, --help[=TAG|KEYWORD] Print usage and exit.
Possible Values: #basic, #advanced, #http, #https, #ftp, #metalink, #bittorrent, #cookie, #hook, #file, #rpc, #checksum, #experimental, #deprecated, #help, #all
Default: #basic
Tags: #basic, #help
--dir=PATH download target directory
Possible Values: /path/to/file
Default: .
Tags: #advanced, #basic
--out=FILE output file name override
Possible Values: FILE
Tags: #advanced, #basic
--split=NUM piece split count
Possible Values: NUM
Default: 5
Tags: #advanced, #basic, #ftp, #http
--continue[=true|false], -c resume partial download
Possible Values: true, false
Default: false
Tags: #advanced, #basic
--enable-rpc[=true|false] enable rpc server
Possible Values: true, false
Default: false
Tags: #basic, #rpc
--rpc-listen-port=PORT rpc tcp port
Possible Values: PORT
Default: 6800
Tags: #basic, #rpc
--rpc-listen-all[=true|false] bind rpc server to all interfaces
Possible Values: true, false
Default: false
Tags: #basic, #rpc
--rpc-secret=VALUE rpc auth token
Tags: #basic, #rpc
--listen-port=PORT bt tcp/udp listen port
Possible Values: PORT
Default: 6881
Tags: #basic, #bittorrent
--dht-listen-port=PORT dht udp listen port
Possible Values: PORT
Default: 6881
Tags: #basic, #bittorrent
--bt-tracker=URI,... bt tracker announce list
Possible Values: URI,...
Tags: #basic, #bittorrent
--on-download-complete=COMMAND completion hook command
Possible Values: COMMAND
Tags: #advanced, #basic
--on-download-stop=COMMAND stop hook command
Possible Values: COMMAND
Tags: #advanced, #basic
--disable-ipv6[=true|false] disable ipv6 sockets and resolution
Possible Values: true, false
Default: true
Tags: #basic
--user-agent=VALUE, -U request user agent header
Tags: #basic, #http
--header=HEADER custom request headers
Possible Values: HEADER
Tags: #basic, #http
--all-proxy=URI generic proxy endpoint
Possible Values: URI
Tags: #basic, #ftp, #http
--http-proxy=URI http proxy endpoint
Possible Values: URI
Tags: #basic, #ftp, #http
--https-proxy=URI https proxy endpoint
Possible Values: URI
Tags: #basic, #ftp, #http
--no-proxy=HOST,... proxy bypass host list
Possible Values: HOST,...
Tags: #basic, #ftp, #http
--check-certificate[=true|false] verify peer and host certificates
Possible Values: true, false
Default: true
Tags: #basic, #https
--ca-certificate=PATH ca certificate file
Possible Values: /path/to/file
Tags: #basic, #https
--certificate=PATH client certificate file
Possible Values: /path/to/file
Tags: #basic, #https
--private-key=PATH client private key file
Possible Values: /path/to/file
Tags: #basic, #https
--retry-wait=SEC retry delay in seconds
Possible Values: SEC
Default: 0
Tags: #basic, #http
--max-tries=NUM maximum retry attempts
Possible Values: NUM
Default: 5
Tags: #basic, #http
--bt-save-metadata[=true|false] save metadata file
Possible Values: true, false
Default: false
Tags: #basic, #bittorrent
--follow-torrent=true|false|mem torrent follow behavior
Possible Values: true|false|mem
Default: true
Tags: #basic, #bittorrent
--metalink-enable-unique-protocol[=true|false]
metalink dedupe by protocol
Possible Values: true, false
Default: true
Tags: #basic, #metalink
--max-overall-download-limit=SIZE global aggregate download-speed cap
Possible Values: SIZE
Default: 0
Tags: #advanced, #basic, #bittorrent, #ftp, #http
--max-download-limit=SIZE per-download download-speed cap
Possible Values: SIZE
Default: 0
Tags: #advanced, #basic, #bittorrent, #ftp, #http
--max-overall-upload-limit=SIZE global aggregate upload-speed cap
Possible Values: SIZE
Default: 0
Tags: #advanced, #basic, #bittorrent, #ftp, #http
--max-upload-limit=SIZE per-download upload-speed cap
Possible Values: SIZE
Default: 0
Tags: #advanced, #basic, #bittorrent, #ftp, #http
--disk-cache=SIZE configured disk cache budget
Possible Values: SIZE
Default: 16M
Tags: #advanced, #basic, #ftp, #http
--max-connection-per-server=NUM, -x
legacy speed tuning
Possible Values: NUM
Default: 1
Tags: #advanced, #basic, #ftp, #http
--min-split-size=SIZE pro lower split-size floor target
Possible Values: SIZE
Default: 20M
Tags: #advanced, #basic, #ftp, #http
--piece-length=SIZE pro lower piece-length floor target
Possible Values: SIZE
Default: 1M
Tags: #advanced, #basic, #ftp, #http
--retry-on-400[=true|false] retry HTTP 400 when explicitly enabled
Possible Values: true, false
Default: false
Tags: #basic, #http, #rpc
--retry-on-403[=true|false] retry HTTP 403 when explicitly enabled
Possible Values: true, false
Default: false
Tags: #basic, #http, #rpc
--retry-on-406[=true|false] retry HTTP 406 when explicitly enabled
Possible Values: true, false
Default: false
Tags: #basic, #http, #rpc
--retry-on-unknown[=true|false] retry unknown HTTP failure when explicitly enabled
Possible Values: true, false
Default: false
Tags: #basic, #http, #rpc
--input-file=PATH, -i load uri list from file
Possible Values: PATH
Tags: #advanced, #basic
--save-session=PATH save active tasks on exit
Possible Values: PATH
Tags: #advanced, #basic
--save-session-interval=SEC periodic session flush interval
Possible Values: SEC
Default: 0
Tags: #advanced, #basic
--no-want-digest-header[=true|false], --http-want-digest
compat switch for digest header behavior
Possible Values: true, false
Default: false
Tags: #basic, #experimental, #http
Refer to man page for more information.
@@ -0,0 +1,12 @@
aria2 version 1.37.0
Rust rewrite package: aria2-rust-pro 1.0.0
Compatibility baseline: 1f1323128cae942f5440c035cb5f42788b3de33f
** Configuration **
Enabled Features: Async DNS, BitTorrent, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP
Hash Algorithms: sha-1, sha-224, sha-256, sha-384, sha-512, md5, adler32
Libraries: tokio, reqwest, rustls, quick-xml
System: windows (x86_64)
Report bugs to https://github.com/aria2/aria2/issues
Visit https://aria2.github.io/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
aria2 version 1.37.0
Copyright (C) 2006, 2019 Tatsuhiro Tsujikawa
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
** Configuration **
Enabled Features: Async DNS, BitTorrent, Firefox3 Cookie, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP
Hash Algorithms: sha-1, sha-224, sha-256, sha-384, sha-512, md5, adler32
Libraries: zlib/1.3 expat/2.5.0 sqlite3/3.43.1 GMP/6.3.0 c-ares/1.19.1 libssh2/1.11.0
Compiler: mingw-w64 8.0.0 (alpha) / gcc 10-win32 20220113
built by x86_64-pc-linux-gnu
targeting x86_64-w64-mingw32
on Nov 15 2023 11:17:49
System: Windows 6.2 (x86_64) (6.2)
Report bugs to https://github.com/aria2/aria2/issues
Visit https://aria2.github.io/
+223
View File
@@ -0,0 +1,223 @@
# Deployment Guide
This is the concrete deployment guide for the current `aria2-rust-pro`
repository state. It covers the two deployable paths that exist today:
- native host deployment from a local Cargo build
- local Docker deployment from `docker/Dockerfile`
For migration-specific advice, start with [../migration/README.md](../migration/README.md).
## Current Deployment Facts
- Native host installs are source-build-first today.
- The self-hosted Gitea `v1.0.0` release carries the first Windows archive,
Docker image tar, manifests, and checksum assets.
- Docker deployment is still local-build-first or tar-import-first; there is
no documented published container registry tag yet.
- Native RPC startup requires `--enable-rpc` on the command line. Putting
`enable-rpc=true` only in the config file is not enough to switch the CLI
into the long-running RPC server path.
- `--daemon` currently selects the RPC-daemon command surface; it should not be
treated as a service-manager replacement or as proof of POSIX background
forking.
## Native Host Deployment
### 1. Build the binary
```powershell
cargo build --release -p aria2-rust-pro-cli --bin aria2-rust-pro
```
The resulting binary is:
- Windows: `target\release\aria2-rust-pro.exe`
- Linux: `target/release/aria2-rust-pro`
### 2. Prepare the runtime directories
On Windows, a simple starting layout is:
```powershell
$Root = "C:/ProgramData/aria2-rust-pro"
New-Item -ItemType Directory -Force "$Root", "$Root/downloads", "$Root/state" | Out-Null
Copy-Item .\docs\deployment\examples\aria2.conf "$Root/aria2.conf"
```
On Linux, the same layout works under `/var/lib/aria2-rust-pro` or
`/srv/aria2-rust-pro`.
Edit the copied config so that `dir=`, `input-file=`, and `save-session=` point
at your real directories, and replace `rpc-secret=` with a strong private value
before enabling RPC. A ready-to-edit template lives at
[examples/aria2.conf](examples/aria2.conf).
### 3. Validate the config
```powershell
.\target\release\aria2-rust-pro.exe --dry-run --conf-path C:/ProgramData/aria2-rust-pro/aria2.conf
```
This should exit cleanly with no config-parse error.
### 4. Start the RPC process
For a direct foreground launch:
```powershell
.\target\release\aria2-rust-pro.exe --conf-path C:/ProgramData/aria2-rust-pro/aria2.conf --enable-rpc
```
For Linux service managers, keep the process in the foreground and let the
supervisor own restart behavior. A sample unit file lives at
[examples/aria2-rust-pro.service](examples/aria2-rust-pro.service).
### 5. Verify the deployment
Version:
```powershell
.\target\release\aria2-rust-pro.exe --version
```
RPC probe:
```powershell
xh post http://127.0.0.1:6800/jsonrpc jsonrpc=2.0 id=deploy method=aria2.getVersion params:='["token:replace-with-a-strong-rpc-secret"]'
```
Session file presence:
```powershell
Test-Path C:/ProgramData/aria2-rust-pro/state/aria2.session
```
## Docker Deployment
`docker/Dockerfile`, `docker/entrypoint.sh`, and the Cargo-native Docker smoke
commands define the current Docker deployment shape. Use the daemon-free and
daemon-backed smokes below to verify the current workspace snapshot before
calling a local deployment ready.
When the daemon is available, a portable local image tar can also be staged
with `xtask docker export-local`; `scripts/docker/export-local.ps1` remains a
compatibility wrapper.
### 1. Prepare the env file
Copy [../../docker/.env.example](../../docker/.env.example) to `docker/.env`
and replace the example values:
```powershell
Copy-Item .\docker\.env.example .\docker\.env
```
Set a strong `RPC_SECRET` before starting compose. The compose file refuses an
empty secret and binds the host RPC port to `127.0.0.1` by default; widen
`RPC_BIND_ADDRESS` only when the host network is trusted.
### 2. Review the persistent volume paths
`docker/docker-compose.yml` currently mounts:
- `../.local/docker/config` to `/config`
- `../.local/docker/downloads` to `/downloads`
If your persistent data lives elsewhere, change those bind mounts before the
first start.
### 3. Build and start the container
```powershell
docker compose --env-file docker/.env -f docker/docker-compose.yml up -d --build
```
This builds `aria2-rust-pro:local`, starts the `aria2-rust-pro` container, and
exposes the configured RPC and listen ports.
### 4. Inspect the generated runtime config
```powershell
docker exec aria2-rust-pro sh -lc "sed 's/^rpc-secret=.*/rpc-secret=<redacted>/' /run/aria2-rust-pro/aria2.generated.conf"
```
The entrypoint:
- copies `/defaults/aria2.conf` to `/config/aria2.conf` only when the base file
does not already exist
- ensures `/config/aria2.session` exists
- appends env-derived overrides into
`/run/aria2-rust-pro/aria2.generated.conf`
### 5. Verify RPC and logs
Logs:
```powershell
docker compose --env-file docker/.env -f docker/docker-compose.yml logs -f
```
Version inside the container:
```powershell
docker exec aria2-rust-pro aria2c --version
```
RPC probe from the host:
```powershell
xh post http://127.0.0.1:6800/jsonrpc jsonrpc=2.0 id=deploy method=aria2.getVersion params:='["token:replace-with-a-strong-rpc-secret"]'
```
### Current Docker behavior
The current entrypoint does more than simple port/env mapping:
- it seeds `bt-tracker=` from `docker/defaults/bt-tracker.txt`
- `SPECIAL_MODE=move` or `SPECIAL_MODE=rclone` appends
`on-download-complete=...`
- `UPDATE_TRACKERS=true` runs the bundled tracker updater script
Those entrypoint behaviors are covered by both `xtask docker smoke-local` and
the daemon-backed `xtask docker smoke`. The live container path now boots,
serves RPC, and keeps those Docker-specific config rewrites active in
`/run/aria2-rust-pro/aria2.generated.conf`.
## Smoke Commands
Use the canonical Cargo-native smoke commands after any packaging or deployment
change:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke-local
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke --tag aria2-rust-pro:smoke
```
`xtask docker smoke-local` proves the entrypoint/config-generation path without
a Docker daemon. `xtask docker smoke` builds the image and probes live JSON-RPC
inside a running container.
The PowerShell scripts remain compatibility wrappers with the same local
options:
```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\docker\smoke-local.ps1
powershell -ExecutionPolicy Bypass -File .\scripts\docker\smoke.ps1 -Tag aria2-rust-pro:smoke
```
The daemon-backed wrapper forwards `-Build`, `-HostRpcPort`, `-RpcSecret`, and
`-SpecialMode` to the matching `xtask docker smoke` options.
## Known Deployment Limits Today
- No documented published image tag yet; Docker deployment is still
local-build-first or tar-import-first from the release asset.
- The self-hosted Gitea `v1.0.0` release includes the first Windows archive and
Docker tar assets; a broader multi-platform archive matrix is still future
work.
- The Docker entrypoint now applies tracker snapshot, tracker-update, and
special-mode hook rewrites, but this is still a local-build-first deployment
lane rather than a published image-release matrix.
- The repo ships a sample systemd unit, but not a first-party Windows service
wrapper or installer.
@@ -0,0 +1,18 @@
[Unit]
Description=aria2-rust-pro RPC service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aria2
Group=aria2
WorkingDirectory=/var/lib/aria2-rust-pro
ExecStart=/opt/aria2-rust-pro/bin/aria2-rust-pro --conf-path /etc/aria2-rust-pro/aria2.conf --enable-rpc
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
+20
View File
@@ -0,0 +1,20 @@
# Minimal native deployment template for aria2-rust-pro.
# Edit the paths and rpc-secret before first use.
dir=/srv/aria2-rust-pro/downloads
input-file=/srv/aria2-rust-pro/state/aria2.session
save-session=/srv/aria2-rust-pro/state/aria2.session
save-session-interval=60
continue=true
split=5
max-connection-per-server=16
min-split-size=1K
piece-length=1K
enable-rpc=true
rpc-listen-port=6800
rpc-secret=replace-with-a-strong-rpc-secret
listen-port=6888
dht-listen-port=6888
disable-ipv6=true
disk-cache=64M
check-certificate=true
+188
View File
@@ -0,0 +1,188 @@
# Migration Guide
This guide reflects the current active modernization state from
`GOAL-modern.md` and `progress.md` for `aria2-rust-pro`. It is written for two
existing audiences:
- users migrating from the [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
host binary
- users running the current `Aria2-Pro-Docker` container shape
The short version is:
- aria2-style config syntax, session files, and RPC clients are intended to
carry forward
- the native host binary is now `aria2-rust-pro`, not a published
`aria2-pro-core` drop-in tarball
- the Docker image keeps the legacy env variable names and now maps the current
Pro Docker knobs through the entrypoint/runtime config path
## Before You Cut Over
Make a copy of the three things that matter before any migration:
1. your current `aria2.conf`
2. your `aria2.session` plus any adjacent `.aria2` control files
3. the exact runtime command or compose file you use today
For Docker users, also record the current bind mounts or named volumes so that
you know where `/config` and `/downloads` live on disk.
## Compatibility Snapshot
| Surface | Current `aria2-rust-pro` status | Migration meaning |
| --- | --- | --- |
| aria2-style config file | compatible target; current parser/runtime covers the common Pro/Core and Docker paths used here | keep your existing config and validate it with `--dry-run` before switching traffic |
| Session and input files | current session persistence is implemented and covered by tests | keep existing session paths; do not delete `aria2.session` during cutover |
| JSON-RPC and XML-RPC | current RPC surface is implemented enough for representative aria2 clients | reuse the same client URLs and tokens after you verify the new port and secret |
| Native packaging | the public `v1.0.0` release is a source snapshot; local packaging commands produce host-specific artifacts | plan for a local Cargo build or your own packaged artifact |
| Docker env names | the current Pro Docker env set is accepted and mapped by the entrypoint | keep the same env names, then verify the generated runtime config before cutover |
## From [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
### What stays the same
- Keep your existing `aria2.conf` format.
- Keep your current `aria2.session`.
- Keep the Pro/Core option deltas that already exist in this rewrite, including
the relaxed split and retry knobs tracked in the compatibility ledger.
### What changes
| Area | Old Core habit | `aria2-rust-pro` now |
| --- | --- | --- |
| Binary name | usually `aria2c` | native host binary is `aria2-rust-pro` |
| Install flow | download a release tarball and move `aria2c` into place | build with Cargo or deploy your own packaged artifact |
| RPC startup | config plus your old service wrapper | native startup still needs `--enable-rpc` on the command line to enter the long-running RPC server path |
| Backgrounding | old wrappers often daemonized the process | do not rely on `--daemon` as a POSIX fork; supervise the foreground process with systemd, NSSM, Task Scheduler, or another service manager |
### Recommended host cutover
1. Build the new binary without overwriting the old one yet:
```powershell
cargo build --release -p aria2-rust-pro-cli --bin aria2-rust-pro
```
2. Stage a new config root and copy your current config/session into it.
3. Validate the config before swapping any service definition:
```powershell
.\target\release\aria2-rust-pro.exe --dry-run --conf-path C:/ProgramData/aria2-rust-pro/aria2.conf
```
4. Update your service or launcher to point at the new binary and keep
`--enable-rpc` on the command line:
```powershell
.\target\release\aria2-rust-pro.exe --conf-path C:/ProgramData/aria2-rust-pro/aria2.conf --enable-rpc
```
5. Probe RPC before you disable the old service:
```powershell
xh post http://127.0.0.1:6800/jsonrpc jsonrpc=2.0 id=migrate method=aria2.getVersion params:='["token:replace-with-a-strong-rpc-secret"]'
```
If your surrounding scripts still hardcode `aria2c`, keep the old binary in
place until you have either updated those scripts or installed your own wrapper
or symlink that points `aria2c` to `aria2-rust-pro`.
## From `Aria2-Pro-Docker`
### What carries forward
- `/config/aria2.conf` remains the base config path.
- `/config/aria2.session` remains the session file path.
- `/downloads` remains the default download root.
- the container still accepts the familiar Pro Docker env variable names
### What is different from the old Docker behavior
| Env or behavior | Old Pro Docker expectation | `aria2-rust-pro` now |
| --- | --- | --- |
| `RPC_SECRET` | old images often rewrote `aria2.conf` in place and could expose compatibility fallbacks | when set, it appends `rpc-secret` and `rpc-listen-all=true` into the generated runtime config; when empty, the entrypoint warns and keeps RPC loopback-only unless your base config overrides it |
| `RPC_PORT` | runtime env + config rewrite | mapped into `/run/aria2-rust-pro/aria2.generated.conf` |
| `LISTEN_PORT` | runtime env + config rewrite | mapped into generated config for both `listen-port` and `dht-listen-port` |
| `DISK_CACHE` | runtime env + config rewrite | mapped into generated config |
| `IPV6_MODE` | runtime env + config rewrite | mapped into generated config as `disable-ipv6=true/false` |
| `UPDATE_TRACKERS` | functional startup/runtime knob | supported by the entrypoint; when enabled it runs the bundled tracker updater against the generated config |
| `CUSTOM_TRACKER_URL` | functional tracker-updater input | supported by the entrypoint as the tracker updater source URL |
| `SPECIAL_MODE` | functional mode hook | supported by the entrypoint for `move` and `rclone`; it copies default scripts and appends `on-download-complete=` to the generated config |
| Config mutation | old image families often rewrote `/config/aria2.conf` directly | this image copies `/config/aria2.conf` only when missing, then writes overrides to `/run/aria2-rust-pro/aria2.generated.conf` |
### Recommended Docker staging flow
1. Stop the old container without deleting the existing `/config` and
`/downloads` data.
2. Copy `docker/.env.example` to `docker/.env` and set your real values.
3. If your current data lives somewhere other than the compose defaults, adjust
the volume paths in `docker/docker-compose.yml` before first start.
4. Build and start the replacement container:
```powershell
docker compose --env-file docker/.env -f docker/docker-compose.yml up -d --build
```
5. Confirm that the container preserved the base config and generated the
runtime overlay:
```powershell
docker exec aria2-rust-pro sh -lc "test -f /config/aria2.conf && sed 's/^rpc-secret=.*/rpc-secret=<redacted>/' /run/aria2-rust-pro/aria2.generated.conf"
```
6. Probe RPC from the host:
```powershell
xh post http://127.0.0.1:6800/jsonrpc jsonrpc=2.0 id=migrate method=aria2.getVersion params:='["token:replace-with-a-strong-rpc-secret"]'
```
### Current Docker status
The Docker deployment lane is now materially real:
- `xtask docker smoke-local` verifies entrypoint/config generation without a
daemon
- `xtask docker smoke` builds the image, starts the container, verifies
`aria2c --version`, checks the generated runtime config, and probes live
JSON-RPC
- `xtask docker export-local` can stage a portable image tar under
`dist\docker\` when the daemon is reachable
The matching `scripts/docker/*.ps1` files remain thin compatibility wrappers
for existing local workflows.
The entrypoint now:
- seeds a bundled `bt-tracker=` snapshot when the config leaves it empty
- honors `UPDATE_TRACKERS` and `CUSTOM_TRACKER_URL` through the bundled tracker
updater
- honors `SPECIAL_MODE=move` and `SPECIAL_MODE=rclone` by materializing the
matching hook scripts and appending `on-download-complete=...`
That makes the safe migration posture for existing Pro Docker users:
- stage the new image with the same `/config` and `/downloads` data
- inspect `/run/aria2-rust-pro/aria2.generated.conf` after first boot
- probe RPC before switching user traffic
Inside the container, `/usr/local/bin/aria2c` is a symlink to
`/usr/local/bin/aria2-rust-pro`, so tools that `docker exec ... aria2c ...`
still work after the image swap.
## Rollback
Keep rollback boring:
1. stop the new host service or container
2. restore the old binary or old image reference
3. put back the backed-up `aria2.conf` and `aria2.session`
4. start the old deployment shape again
Rollback is much easier if you do not overwrite the old host binary path or
delete the old Docker volumes until the RPC probe and a small real download
both pass on the new deployment.
+21
View File
@@ -0,0 +1,21 @@
# Performance Evidence
Performance evidence starts here. This directory records benchmark design notes and measured results.
As of the Phase 3 Cargo-native workflow push, the canonical report-refresh
entrypoint is:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- perf collect-local-comparison
```
`scripts/perf/collect_local_comparison.ps1` remains available as a thin
compatibility shim for existing local workflows.
Current active performance evidence files:
- `optimization-ranking.md`
- `rpc-pressure-evidence.md`
- `criterion-benchmarks.md`
- `local-comparison.md`
- `size-evidence.md`
+178
View File
@@ -0,0 +1,178 @@
# Criterion Benchmarks
This file records the Criterion-backed benchmark suite for
`aria2-rust-pro`.
## Purpose
This project needs a repeatable benchmark surface in addition to assertion-style
regression tests. This suite converts the existing synthetic BT/RPC pressure
patterns into Criterion benchmarks so later tranches can compare revisions and
resource-limit tuning with the same workload shape.
## Bench Target
- crate: `crates/aria2-rust-pro-tests`
- bench: `rpc_pressure`
## Current Coverage
The current suite measures nine deterministic scenarios:
1. `rpc_tell_status_pressure`
- 64-task and 128-task BT-like dispatcher loads
- repeated `aria2.tellStatus` calls under runtime tick churn
2. `rpc_mixed_pressure`
- 96-task and 192-task BT-like dispatcher loads
- mixed `aria2.tellStatus`, `aria2.tellActive`, and `aria2.tellGlobalStat`
batches
3. `runtime_snapshot_pressure`
- 64 / 128 / 256 download in-memory engine setups
- repeated scheduler runs plus `runtime_instrumentation_snapshot()` capture
4. `rpc_speed_limit_pressure`
- 32-task and 64-task BT-like dispatcher loads
- active `changeGlobalOption` / `changeOption` speed caps
- repeated `tellStatus` plus `tellGlobalStat` under clamped runtime speeds
5. `scheduler_backpressure_pressure`
- 64-task and 128-task in-memory engine setups
- mixed active/waiting/error groups
- repeated scheduler runs plus runtime instrumentation under differing
`disk-cache` budgets
6. `live_http_transfer_contention_pressure`
- loopback live HTTP transfer via `ReqwestHttpConnector` and
`ConnectorBackedDownloader`
- 16 KiB segmented HTTP downloads that force bootstrap `206` plus follow-up
range requests
- comparison between a loose-cap runtime and a tight
`max-overall-download-limit` runtime so execution-layer throttling is
measured instead of only inferred from RPC snapshots
7. `live_http_multi_download_contention_pressure`
- three concurrent loopback live HTTP downloads
- each download still uses the existing CLI/runtime wiring, but all three
contend against one local segment server at once
- compares loose-cap vs tight-cap runtime configuration under aggregate
multi-download contention
8. `rpc_shared_runtime_fairness_pressure`
- three-way and four-way BT-like dispatcher loads inside one runtime
- one constrained gid completes, then the remaining active gids are expected
to inherit a larger share of the global speed cap
- verifies same-runtime cross-download rebalancing rather than only
per-download segment throttling or separate parallel invocations
9. `live_http_shared_runtime_multi_download_pressure`
- three loopback live HTTP downloads registered into one invocation/runtime
- uses the shared CLI runtime path rather than separate parallel invocations
- compares loose-cap vs tight-cap runtime configuration for same-runtime live
transfer behavior
- now also includes a six-download `tight_cap_6way` variant so shared-runtime
cap behavior is measured beyond the original 3-download / 16 KiB shape
- now also includes `cache_pressure_6way_256k`, which raises per-download
transfer size while constraining `disk-cache` so shared-runtime cache
pressure is represented in the same benchmark family
## Commands
Canonical local report refresh:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- perf collect-local-comparison
pwsh ./scripts/perf/collect_local_comparison.ps1
```
Compile-only verification:
```powershell
rtk cargo bench --manifest-path .\Cargo.toml -p aria2-rust-pro-tests --bench rpc_pressure --no-run
```
Short local run:
```powershell
rtk cargo bench --manifest-path .\Cargo.toml -p aria2-rust-pro-tests --bench rpc_pressure -- --sample-size 10 --measurement-time 0.05 --warm-up-time 0.05
```
## First Short Run Snapshot
Short local run on this workspace produced the following indicative timings:
- `rpc_tell_status_pressure/tell_status/64`
- `1.3318 ms .. 1.3459 ms`
- throughput `190.21 Kelem/s .. 192.22 Kelem/s`
- `rpc_tell_status_pressure/tell_status/128`
- `2.8581 ms .. 2.8726 ms`
- throughput `178.24 Kelem/s .. 179.14 Kelem/s`
- `rpc_mixed_pressure/mixed_rpc/96`
- `59.918 us .. 64.561 us`
- throughput `278.81 Kelem/s .. 300.41 Kelem/s`
- `rpc_mixed_pressure/mixed_rpc/192`
- `78.663 us .. 83.252 us`
- throughput `216.21 Kelem/s .. 228.82 Kelem/s`
- `runtime_snapshot_pressure/runtime_snapshot/64`
- `8.3619 us .. 9.0689 us`
- `runtime_snapshot_pressure/runtime_snapshot/128`
- `15.452 us .. 17.835 us`
- `runtime_snapshot_pressure/runtime_snapshot/256`
- `31.072 us .. 33.087 us`
- `rpc_speed_limit_pressure/speed_limit/32`
- `64.896 us .. 66.191 us`
- throughput `181.29 Kelem/s .. 184.91 Kelem/s`
- `rpc_speed_limit_pressure/speed_limit/64`
- `90.733 us .. 93.649 us`
- throughput `128.14 Kelem/s .. 132.26 Kelem/s`
- `scheduler_backpressure_pressure/backpressure/64`
- `10.917 us .. 12.478 us`
- throughput `5.1290 Melem/s .. 5.8625 Melem/s`
- `scheduler_backpressure_pressure/backpressure/128`
- `19.792 us .. 21.039 us`
- throughput `6.0839 Melem/s .. 6.4673 Melem/s`
- `live_http_transfer_contention_pressure/live_http_transfer/loose_cap`
- `38.640 ms .. 39.143 ms`
- throughput `408.76 KiB/s .. 414.07 KiB/s`
- `live_http_transfer_contention_pressure/live_http_transfer/tight_cap`
- `41.793 ms .. 48.988 ms`
- throughput `326.61 KiB/s .. 382.83 KiB/s`
These are not cross-machine release numbers. They are the first local benchmark
local benchmark anchor so later tuning and regressions can be compared against a
stable local benchmark driver. The new live HTTP group is still loopback-local rather
than internet-realistic, but it now exercises the segmented execution path with
real socket I/O instead of only scheduler-facing synthetic churn.
- `live_http_multi_download_contention_pressure/multi_live_http_transfer/loose_cap`
- `105.63 ms .. 106.46 ms`
- throughput `450.86 KiB/s .. 454.43 KiB/s`
- `live_http_multi_download_contention_pressure/multi_live_http_transfer/tight_cap`
- `105.13 ms .. 105.52 ms`
- throughput `454.90 KiB/s .. 456.56 KiB/s`
- `rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/three_way_rebalance`
- `70.687 us .. 72.082 us`
- throughput `166.48 Kelem/s .. 169.76 Kelem/s`
- `rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/four_way_rebalance`
- `95.853 us .. 96.893 us`
- throughput `165.13 Kelem/s .. 166.92 Kelem/s`
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/loose_cap`
- `107.57 ms .. 108.23 ms`
- throughput `443.49 KiB/s .. 446.23 KiB/s`
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap`
- `118.77 ms .. 120.35 ms`
- throughput `398.83 KiB/s .. 404.14 KiB/s`
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap_6way`
- `234.36 ms .. 236.30 ms`
- throughput `406.26 KiB/s .. 409.63 KiB/s`
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/cache_pressure_6way_256k`
- `96.98 ms .. 99.12 ms`
- throughput `15.133 MiB/s .. 15.466 MiB/s`
## Intended Next Extension
This suite now mixes synthetic pressure and local loopback transfer. The next
tranche should attach:
- comparisons against the upstream [aria2](https://github.com/aria2/aria2)
reference and the [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
reference baseline
- further larger or more realistic same-runtime live transfer workloads beyond
the new 6-download tight-cap and cache-pressure anchors
- stronger disk-cache and backpressure scenarios with larger transfer/runtime
contention
- upstream aria2 / Aria2-Pro-Core reference-baseline comparison notes
- memory and file-descriptor measurements recorded beside benchmark output
+89
View File
@@ -0,0 +1,89 @@
# Local Comparison
Generated: 2026-05-28 12:08:14 +00:00
## Environment
- Repo root: <repo-root>
- Bench executable: <repo-root>\target\release\deps\rpc_pressure-386f010a5bd10aaf.exe
- Manifest: <repo-root>\Cargo.toml
- Bench process exit code: unavailable in this refresh
- Peak working set during local bench run: unavailable in this refresh
- Peak handle count during local bench run: unavailable in this refresh
## Reference Artifact Detection
- Reference projects: [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
and [aria2](https://github.com/aria2/aria2)
- Rust CLI local executable: <repo-root>\target\release\aria2-rust-pro.exe
- Original aria2 local executable: <repo-root>\dist\upstream\aria2-1.37.0-win-64bit-build1\aria2-1.37.0-win-64bit-build1\aria2c.exe
- Original aria2 version summary: aria2 version 1.37.0; Enabled Features: Async DNS, BitTorrent, Firefox3 Cookie, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP; Compiler: mingw-w64 8.0.0 (alpha) / gcc 10-win32 20220113; built by x86_64-pc-linux-gnu; targeting x86_64-w64-mingw32; on Nov 15 2023 11:17:49
- Aria2-Pro-Core reference executable: <aria2-baseline>\build\pro-core\windows-x64-mingw-30403\stage\aria2-pro-core-1.37.0+pro.20260523-windows-x64-mingw\aria2c.exe
- Aria2-Pro-Core reference version summary: aria2 version 1.37.0; Enabled Features: Async DNS, BitTorrent, Firefox3 Cookie, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP; Compiler: mingw-w64 15.0.0 (alpha) / gcc 16.1.0; built by x86_64-w64-mingw32; on May 23 2026 15:48:03; Pro Build: 1.37.0+pro.20260523; Pro Commit: 64365cf3cdca441ab710d53be8e4ded37a9b3d7e
- Comparison status: Rust local benchmarks and expanded same-host loopback HTTP comparisons were executed across Rust, the Aria2-Pro-Core reference baseline, and upstream aria2 on this Windows host.
## Same-Host Local HTTP Transfer Comparisons
- Payload bytes: 8388608
- Payload SHA256: BDF23837181F5808331800C1AE2B4F7D7A839536B10D58491471C50DDE23833A
### single_file_split1
- One loopback HTTP file with split=1 and max-connection-per-server=1
| Binary | Exit code | Samples | Median | Spread | Output count | Output bytes | SHA256 all match |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Rust CLI | 0 | 5 | 132.53 ms | 120.16 .. 138.76 ms | 1 | 8388608 | true |
| Pro Core | 0 | 5 | 199.34 ms | 89.93 .. 211.04 ms | 1 | 8388608 | true |
| Upstream aria2 | 0 | 5 | 181.67 ms | 172.38 .. 202.26 ms | 1 | 8388608 | true |
### segmented_single_file
- One loopback HTTP file with split=4 and max-connection-per-server=4
| Binary | Exit code | Samples | Median | Spread | Output count | Output bytes | SHA256 all match |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Rust CLI | 0 | 5 | 125.49 ms | 121.33 .. 132.76 ms | 1 | 8388608 | true |
| Pro Core | 0 | 5 | 209.49 ms | 208.44 .. 1197.45 ms | 1 | 8388608 | true |
| Upstream aria2 | 0 | 5 | 174.51 ms | 171.90 .. 194.46 ms | 1 | 8388608 | true |
## Rust Criterion Summary
| Benchmark | Mean | 95% CI |
| --- | --- | --- |
| bt_visibility_pressure/bt_visibility/32 | 910.409 us | 905.654 us .. 915.190 us |
| bt_visibility_pressure/bt_visibility/64 | 1.8430 ms | 1.8378 ms .. 1.8490 ms |
| live_http_multi_download_contention_pressure/multi_live_http_transfer/loose_cap | 11.6320 ms | 11.5494 ms .. 11.7368 ms |
| live_http_multi_download_contention_pressure/multi_live_http_transfer/tight_cap | 11.5679 ms | 11.5103 ms .. 11.6136 ms |
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/cache_pressure_6way_256k | 7.2873 ms | 7.1368 ms .. 7.4519 ms |
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/loose_cap | 11.8141 ms | 11.6959 ms .. 11.9347 ms |
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap | 11.8461 ms | 11.7319 ms .. 11.9568 ms |
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap_6way | 12.7498 ms | 12.6485 ms .. 12.8552 ms |
| live_http_transfer_contention_pressure/live_http_transfer/loose_cap | 11.6614 ms | 11.4932 ms .. 11.8646 ms |
| live_http_transfer_contention_pressure/live_http_transfer/tight_cap | 10.9603 ms | 10.8586 ms .. 11.0562 ms |
| rpc_mixed_pressure/mixed_rpc/192 | 135.092 us | 134.021 us .. 136.230 us |
| rpc_mixed_pressure/mixed_rpc/96 | 84.114 us | 82.923 us .. 85.222 us |
| rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/four_way_rebalance | 88.653 us | 87.023 us .. 90.329 us |
| rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/three_way_rebalance | 66.833 us | 65.539 us .. 68.357 us |
| rpc_speed_limit_pressure/speed_limit/32 | 60.370 us | 59.997 us .. 60.762 us |
| rpc_speed_limit_pressure/speed_limit/64 | 90.078 us | 87.568 us .. 93.803 us |
| rpc_tell_status_pressure/tell_status/128 | 2.6805 ms | 2.6576 ms .. 2.7154 ms |
| rpc_tell_status_pressure/tell_status/64 | 1.3265 ms | 1.3112 ms .. 1.3412 ms |
| runtime_snapshot_pressure/runtime_snapshot/128 | 24.534 us | 23.895 us .. 25.183 us |
| runtime_snapshot_pressure/runtime_snapshot/256 | 52.193 us | 48.362 us .. 59.051 us |
| runtime_snapshot_pressure/runtime_snapshot/64 | 13.701 us | 13.281 us .. 14.100 us |
| scheduler_backpressure_pressure/backpressure/128 | 33.341 us | 33.017 us .. 33.630 us |
| scheduler_backpressure_pressure/backpressure/64 | 18.659 us | 18.064 us .. 19.492 us |
## Notes
- This report is a local comparison anchor, not a cross-host release benchmark.
- Memory evidence here is peak working set observed during the benchmark process. Peak handle count is currently only recorded when the runtime can provide it.
- The same-host HTTP comparison now covers a narrow single-connection case (split=1) plus a segmented single-file case (split=4) on the same local loopback server model.
- Each binary/scenario pair now performs one untimed warmup launch followed by repeated timed samples; the side-by-side table reports median elapsed plus fastest..slowest spread so single-run host noise is less likely to dominate the comparison.
- The same-host driver now avoids coarse sleep quantization in its short-process timing and loopback accept path, and it keeps each scenario on one warmed loopback server/port across the timed sample set so Windows first-port cold-path stalls do not dominate the Rust rows.
- Small connector-side wins such as no-proxy reqwest client reuse are still better validated through the direct `ARIA2_RUST_PRO_HTTP_TIMING` breakdown than by whole-process elapsed tables alone.
- The same-host side-by-side table is strongest as a local regression anchor. Some non-Rust reference rows can still pick up host-local cold-path noise, so this report should not be treated as a precision benchmark without corroborating direct runs.
- Shared-runtime multi-download pressure is still represented here through the Rust Criterion anchors rather than the side-by-side table.
- The upstream Windows reference now comes from the official aria2 1.37.0 release artifact downloaded into `<repo-root>\dist\upstream\`.
+283
View File
@@ -0,0 +1,283 @@
# Optimization Ranking
This file is the current Phase 6 ranking for `aria2-rust-pro` Take 2.
It is intentionally evidence-first. Each item below exists because current
benchmarks, size reports, or runtime traces show a real remaining cost or a
real verification gap.
## Current Ranking
### 1. Shared-runtime live HTTP fixed cost
Why it ranks first:
- this is the hottest still-open product path inside the current Phase 6 work
- it already has multiple real wins landed in Take 2
- the latest product-side scheduler change removed the previous loose-cap/cache
pressure cliff, so remaining work is now narrower fixed-cost work rather than
broad fanout underutilization
- it is still the clearest place where a product-side win can move the current
benchmark surface
Current evidence:
- after the latest scheduler and writeback pass, focused Criterion runs now
land at:
- `loose_cap`: `23.429 .. 23.998 ms`
- `tight_cap`: `23.592 .. 24.049 ms`
- `tight_cap_6way`: `26.089 .. 26.510 ms`
- `cache_pressure_6way_256k`: `20.255 .. 21.380 ms`
- after the later CLI config-projection cleanup, exact reruns kept the same
`tight_cap` band and pushed the current shared-runtime `6way` absolute band
materially lower:
- exact `tight_cap`: `23.224 .. 23.603 ms`
- exact `tight_cap_6way`: `13.422 .. 13.824 ms`
- after the latest small-segment probe and admitted-download segment-budget
pass, the current focused shared-runtime band moved again:
- `loose_cap`: `12.567 .. 13.399 ms`
- `tight_cap`: `12.674 .. 13.071 ms`
- `tight_cap_6way`: `13.773 .. 14.212 ms`
- `cache_pressure_6way_256k`: `7.793 .. 8.019 ms`
- the later broader short bench-surface refresh kept that band and improved it
slightly:
- `loose_cap`: `11.696 .. 11.935 ms`
- `tight_cap`: `11.732 .. 11.957 ms`
- `tight_cap_6way`: `12.649 .. 12.855 ms`
- `cache_pressure_6way_256k`: `7.137 .. 7.452 ms`
- Criterion reports significant improvement in all four shared-runtime lanes:
- `loose_cap`: roughly `-7.2% .. -3.4%` wall time
- `tight_cap`: roughly `-4.4% .. -1.6%` wall time
- `tight_cap_6way`: roughly `-31.9% .. -29.3%` wall time
- `cache_pressure_6way_256k`: roughly `-14.9% .. -9.5%` wall time
- the new result is a product-path Phase 6 win: runtime now recognizes the
upstream-compatible `max-concurrent-downloads` surface, does not throttle
already-registered same-runtime HTTP bootstrap work through the smaller
active-download queue value, uses even worker partitioning instead of
under-filling workers on `6 / 5` style workloads, and collapses segment
dispatcher writeback to the final response per download
- before that fix, the loopback driver imposed a serialized service-side floor
near `96 ms` / `192 ms` because one server worker processed `12` / `24`
range requests one at a time with an `8 ms` synthetic response delay
- direct timing with `ARIA2_RUST_PRO_HTTP_TIMING=1` showed that, in the shared
runtime live HTTP path, the dominant remaining fixed cost was in
request/connection/send rather than dispatcher writeback
- the same timing probe also confirmed that bootstrap/segment
`record_http_transfer_result` work is currently `0 ms` on this host in the
hot shared-runtime lane, so further wins need to come from request shape or
transport cost rather than from more dispatcher-writeback trimming
- the latest exact `tight_cap_6way` timing rerun now shows the hot small-file
shared-runtime lane completing all six downloads in the bootstrap request
alone:
- `planned_segments=0` for every download
- `bootstrap_persist_ms=0`
- `bootstrap_record_ms=0`
- per-request `send_ms` is now typically `10 .. 11 ms` on top of the driver
`8 ms` response delay
- that means the previous app-side bookkeeping cliff is gone in this lane; the
remaining cost is now mostly transport-side send/response floor rather than a
large remaining dispatcher or persistence tax
- after the latest writeback and segment-tag cleanup, targeted reruns from the
current tree show the larger segmented/cache-pressure lane is back in the
fast band and the small 6-way lane improves again:
- `tight_cap_6way`: `13.008 .. 13.228 ms`
- `cache_pressure_6way_256k`: `7.819 .. 7.988 ms`
- after the latest reqwest prepared-request contention pass, focused exact
reruns stay in the same fast band while trimming one more product-path fixed
cost in the shared-runtime connector hot path:
- `tight_cap_6way`: mean about `13.117 ms`
- `cache_pressure_6way_256k`: mean about `7.900 ms`
- root cause for that pass: in concurrent shared-runtime small-file bursts, the
private prepared-request cache could become mostly contention cost because
many one-shot URI shapes fought over the same mutex before any real reuse
existed
- the current connector now treats prepared-request caching as opportunistic:
repeated shapes still reuse cached URL/header preparation when the lock is
available, but contended callers fall back to local uncached preparation
instead of blocking on the cache mutex
- this pass specifically addresses the broader segmented workload instead of
spending more time on the already near-floor no-follow-up small-file path
Already-landed wins in this lane:
- shared default reqwest client reuse for no-proxy traffic
- initial probe widened from `bytes=0-0` to the first real segment span
- tiny post-probe tails that would previously fan out into three one-alignment
follow-up requests are now coalesced into two larger follow-up requests
- small-alignment segmented transfers now let the initial range probe cover two
complete `max-connection-per-server` windows, reducing real follow-up range
request count for small live HTTP transfers
- shared-runtime segment fanout now budgets against already-admitted downloads
rather than reusing the smaller active-download queue cap after admission
- the live reqwest connector now also raises its same-host idle connection
budget, keeps idle range-transfer connections warm for short bursts, and
enables TCP keepalive; the broader bench-surface rerun kept live HTTP lanes
fast after this connector change
- `max-concurrent-downloads` is now part of the compat option registry and
runtime projection, with an upstream-compatible default of `5`
- small static HTTP work sets are partitioned evenly across available workers
instead of using contiguous chunks that can under-fill the thread set
- shared-runtime follow-up records now update dispatcher state once per
download from the final segment response, instead of once per range response
- direct URI dispatcher registration
- incremental verified-prefix writeback
- shared-runtime follow-up dispatch through one connection-budgeted segment
batch
- no-clone first-attempt retry fast path
- concurrent loopback segment-server handling in the Criterion suite, which
prevents synthetic service-side serialization from hiding client/runtime
concurrency
- shared-runtime follow-up segments now execute through one batched fanout based
on active downloads and `max-connection-per-server`, instead of spawning
nested per-download segment workers during bootstrap preparation
- live streamed response sinks no longer perform an explicit file flush after
every `reqwest::blocking::Response::copy_to`; write/copy errors are still
surfaced, while range-heavy live transfers avoid a repeated per-response
writeback tax
- shared-runtime segment batches now carry the download index as the tag and
store each segment target path once per download, removing one `PathBuf` clone
per planned segment and reducing batch-result allocation churn
- reqwest prepared live-request caching now falls back to local request
preparation when the shared cache lock is contended, which keeps repeated
range-request reuse available without forcing one-shot concurrent request
bursts to wait on the cache mutex
Explicitly not counted as a measured shared-runtime win yet:
- proxy-specific reqwest clients are cached by proxy config, but there is still
no dedicated proxy-path benchmark proving its standalone impact; keep it as
sensible hot-path cleanup rather than counting it as ranked measured evidence
What still looks promising:
- lower per-request request/connection/send overhead
- more disciplined validation of where blocking reqwest still pays fixed cost
- only product-path reductions, not benchmark-only cosmetics
What has already been tried and rejected:
- forcing shared-runtime follow-up parallelism to honor the global overall cap
regressed the lane by about `9% .. 10%`
- swapping the local worker batches to rayon did not produce a meaningful win
- leaking prepared-request state into the public `HttpRequestModel` was rejected;
the kept version confines reqwest-specific URL/header preparation cache state
to `ReqwestHttpConnector`
### 2. Binary size pressure from the RPC + HTTP/TLS stack
Why it ranks second:
- size evidence is now in-tree and clearly points at one dominant cluster
- the current binary is already smaller than both the checked C++ Pro Core and
the upstream Windows binary, so this is no longer emergency work
- there is still a clear future size lane, but it is less urgent than the live
shared-runtime HTTP hot path
Current evidence:
- current Windows Rust binary: `4.94 MiB` (`5,184,512` bytes)
- current checked upstream Windows aria2 binary: `5.39 MiB`
- current checked C++ Pro Core binary: `10.88 MiB`
- top `cargo bloat --crates` buckets are:
- `aria2_rust_pro_rpc`
- `reqwest`
- `rustls`
- `std`
- `aria2_rust_pro_protocol`
Interpretation:
- deeper size work should focus on the combined RPC + HTTP/TLS surface
- one recent owned-code win already landed inside the CLI bucket by replacing
repeated config `BTreeMap<String, String>` materialization with direct
last-wins directive lookup, which notably shrank
`derive_http_session`, `derive_runtime_config`, and
`build_ftp_transfer_parts`
- current CLI-side LLVM IR evidence is refreshed at `53,272` total lines across
`307` function copies, down from the older `59,204` / `320` snapshot
- this is now a ranked future optimization lane, not a closure blocker by
itself
### 3. RPC pressure guard depth
Why it ranks third:
- current synthetic RPC responsiveness evidence now covers both a deterministic
integration guard and Criterion pressure anchors
- this remains a ranked lane because the workload is still synthetic and should
not be overclaimed as a public-swarm certification
- it is no longer an immediate Phase 6 evidence blocker
Current evidence:
- the current pressure guards:
- repeated `tellStatus`
- sampled `getFiles`
- repeated `tellActive`
- repeated `tellGlobalStat`
- BT-like synthetic runtime churn
- the denser mixed guard now covers 96 BT-like magnet tasks over 6 rounds,
including 576 `tellStatus` calls and 72 sampled `getFiles` calls under
per-download runtime tick churn
- current Criterion anchors include:
- `rpc_mixed_pressure/mixed_rpc/96`: `92.383 us`
- `rpc_mixed_pressure/mixed_rpc/192`: `175.169 us`
- `bt_visibility_pressure/bt_visibility/32`: `2.3293 ms`
- `bt_visibility_pressure/bt_visibility/64`: `2.1302 ms`
- the current guard is documented in `rpc-pressure-evidence.md`
- that document explicitly says the thresholds are broad and not a final
performance certification
Needed future expansion:
- higher scheduler pressure
- clearer resource counters suitable for long-term perf reporting
### 4. Same-host comparison noise and interpretation discipline
Why it still matters:
- the local comparison report is now useful and much less misleading than it
used to be
- but it is still a whole-process host-local comparison, not a precision
microbenchmark
Current evidence:
- `local-comparison.md` now reports medians and spread after warmup
- the driver no longer suffers from coarse accept/sleep quantization
- the Rust rows now complete with matching payload size and SHA256
Interpretation:
- this report is good enough to act as a local regression anchor
- it should not be overclaimed as precise proof for micro-optimizations
## Current Phase 6 Read
What is already true:
- benchmark evidence exists
- size/bloat evidence exists
- multiple real product-side wins are already landed and documented
- the current hottest open lane is identified and ranked
- non-HTTP RPC and BT-visibility pressure now have current deterministic and
Criterion evidence
- the Phase 6 shared-runtime loose-cap/cache cliff is fixed by product code,
not by benchmark-only masking
- current broader bench, bloat, binary-size, and LLVM-lines evidence are now
synchronized with the latest Phase 6 tree
What is not yet honest to claim:
- that the shared-runtime live HTTP lane is fully exhausted
- that size work is fully exhausted
- that the current RPC pressure guard is a public-network performance
certification
## References
- `progress.md`
- `docs\perf\local-comparison.md`
- `docs\perf\rpc-pressure-evidence.md`
- `docs\perf\size-evidence.md`
+82
View File
@@ -0,0 +1,82 @@
# RPC Pressure Evidence
This file records the current synthetic RPC responsiveness guard for
`aria2-rust-pro`.
## Scope
Current guard coverage is synthetic but no longer limited to a single
`tellStatus` loop:
- in-process dispatcher
- BT-like magnet workload
- repeated `aria2.tellStatus`
- sampled `aria2.getFiles`
- repeated `aria2.tellActive`
- repeated `aria2.tellGlobalStat`
- Criterion `rpc_mixed_pressure` and `bt_visibility_pressure` anchors
This is not a public-swarm benchmark. It is a deterministic regression guard
for scheduler/RPC responsiveness while the runtime is still approximation-heavy.
## Guard Tests
- `rpc_bt_pressure_guard_keeps_status_active_and_global_stat_responsive`
- `rpc_bt_mixed_pressure_guard_covers_churned_status_files_and_global_views`
Basic guard shape:
- 64 BT-like magnet tasks
- 4 pressure rounds
- 256 total `tellStatus` calls
- 4 `tellActive` calls
- 4 `tellGlobalStat` calls
- runtime tick updates injected during the loop to keep non-zero BT-like state
Mixed guard shape:
- 96 BT-like magnet tasks
- 6 pressure rounds
- 576 total `tellStatus` calls
- 72 sampled `getFiles` calls
- 6 `tellActive` calls
- 6 `tellGlobalStat` calls
- per-download runtime tick churn before every status probe
## Current Thresholds
These thresholds are deliberately broad. They are there to catch obvious
regressions, not to certify final performance:
- cumulative `tellStatus` time across the run: `<= 2000ms`
- cumulative `tellActive` time across the run: `<= 500ms`
- cumulative `tellGlobalStat` time across the run: `<= 500ms`
- cumulative mixed guard time across the run: `<= 4000ms`
## Current Criterion Anchors
Current focused Criterion runs on this host:
| Benchmark | Mean | 95% CI |
| --- | ---: | ---: |
| `rpc_mixed_pressure/mixed_rpc/96` | `92.383 us` | `90.867 .. 93.895 us` |
| `rpc_mixed_pressure/mixed_rpc/192` | `175.169 us` | `160.464 .. 192.884 us` |
| `bt_visibility_pressure/bt_visibility/32` | `2.3293 ms` | `1.0756 .. 4.0986 ms` |
| `bt_visibility_pressure/bt_visibility/64` | `2.1302 ms` | `2.0707 .. 2.2057 ms` |
Interpretation:
- the deterministic integration tests now cover mixed BT/RPC status, file, and
global-stat surfaces under runtime churn
- the Criterion anchors give a current non-HTTP performance regression guard
- the thresholds remain intentionally broad so host-local noise does not turn a
synthetic guard into a flaky gate
## Next Steps
Further work should extend this guard with:
- explicit scheduler tick pressure
- resource counters suitable for later perf reporting
- a documented comparison against the C++ reference once comparable benchmark
suites exist
+137
View File
@@ -0,0 +1,137 @@
# Size Evidence
This file records the current binary-size and code-size evidence for
`aria2-rust-pro` in Take 2 of the modernization goal.
## Commands
```powershell
rtk cargo build --release -p aria2-rust-pro-cli --manifest-path .\Cargo.toml -j $env:NUMBER_OF_PROCESSORS
rtk cargo bloat --release -p aria2-rust-pro-cli --bin aria2-rust-pro --crates -n 40 -j $env:NUMBER_OF_PROCESSORS
rtk cargo rustc --release -p aria2-rust-pro-cli --bin aria2-rust-pro --manifest-path .\Cargo.toml -- --emit=llvm-ir
rtk cargo llvm-lines --files target\release\deps\aria2_rust_pro.aria2_rust_pro_cli-d4c445ae209bfe38.aria2_rust_pro_cli.b493e489391677ca-cgu.0.rcgu.o.rcgu.ll
```
## Binary Size Snapshot
Measured on the current Windows host:
| Binary | Bytes | MiB |
| --- | ---: | ---: |
| `aria2-rust-pro.exe` | `5,213,184` | `4.97` |
| current C++ Pro Core `aria2c.exe` | `11,412,480` | `10.88` |
| upstream Windows `aria2c.exe` | `5,649,408` | `5.39` |
Observations:
- the current Rust binary is about `54.3%` smaller than the current C++ Pro Core
artifact on this host
- the current Rust binary remains about `7.7%` smaller than the upstream
Windows aria2 binary as well
- the latest reduction came from making the release profile more artifact-shaped:
`codegen-units = 1`, `lto = "thin"`, and `strip = "symbols"`
- a later Phase 6 config-projection cleanup removed another small tranche by
replacing repeated release-path `BTreeMap<String, String>` materialization
with last-wins directive lookup on demand
- the latest checked tree, after the recent structural scheduler/DHT cleanup,
leaves the release artifact at `5,213,184` bytes, up `28,672` bytes from the
previous recorded snapshot rather than down
- the host artifact still stays below both checked C++ references
## Cargo Bloat Summary
Current top crate contributions from `cargo bloat --crates`:
| Crate | `.text` size |
| --- | ---: |
| `std` | `815.4 KiB` |
| `aria2_rust_pro_rpc` | `488.4 KiB` |
| `rustls` | `421.7 KiB` |
| `aria2_rust_pro_cli` | `246.7 KiB` |
| `aria2_rust_pro_protocol` | `236.3 KiB` |
| `reqwest` | `213.9 KiB` |
| `ring` | `124.2 KiB` |
| `hyper_util` | `107.8 KiB` |
| `hyper` | `104.2 KiB` |
| `aria2_rust_pro_core` | `100.6 KiB` |
| `tokio` | `94.4 KiB` |
Headline totals from the same run:
- `.text` section: about `3.6 MiB`
- file size from the bloat run: about `5.0 MiB`
Interpretation:
- the biggest owned size buckets are `aria2_rust_pro_rpc`,
`aria2_rust_pro_protocol`, `aria2_rust_pro_cli`, and `aria2_rust_pro_core`
- the biggest third-party buckets are the HTTP/TLS stack:
`reqwest`, `rustls`, `hyper`, `hyper_util`, `tokio`, and `ring`
- future size work should therefore focus on:
- whether the default host binary really needs the full RPC/TLS surface in one
always-on artifact
- whether reqwest / rustls features can be trimmed without breaking the
compatibility contract
- whether any always-linked RPC/HTTP helpers can be split or made less eager
- whether a future release flow should emit a stripped end-user artifact plus
a separate debug-symbol artifact rather than making local release builds do
both jobs at once
- within the owned CLI bucket, the same config-projection cleanup previously cut several
previously ranked helpers materially in the filtered `cargo bloat` view:
- `run_from_env`: `31.2 KiB` -> `30.2 KiB`
- `projection::derive_http_session`: `8.6 KiB` -> `5.7 KiB`
- `projection::derive_runtime_config`: `8.3 KiB` -> `4.0 KiB`
- `build_ftp_transfer_parts`: `6.4 KiB` -> `3.9 KiB`
## LLVM Lines Snapshot
Direct `cargo llvm-lines --release -p aria2-rust-pro-cli --bin aria2-rust-pro`
currently fails on this Windows/MSVC host while linking the temporary
`cargo-llvm-lines` crate, with many unresolved external symbols. The project
itself still builds in release mode; the failure is limited to that tool's
temporary relink path.
The usable current workaround is:
1. emit release LLVM IR with `cargo rustc -- --emit=llvm-ir`
2. point `cargo llvm-lines --files` at the generated CLI `.ll` file
That current CLI crate IR snapshot reports:
- total: `53,272` LLVM IR lines across `307` function copies
- top entries:
- `runtime_host::execute_run_invocation`: `5,538` lines
- `run_from_env`: `4,380` lines
- `parallel_http_runtime::execute_parallel_http_entries`: `3,751` lines
- `http_runtime::execute_segment_transfers`: `2,364` lines
- `http_runtime::execute_tagged_segment_transfers_with_parallelism`: `2,345`
lines
- `runtime_summary::collect_runtime_execution_summary`: `1,207` lines
Interpretation:
- the largest CLI-side IR buckets now line up with the Phase 6 runtime and HTTP
transfer paths rather than a random unrelated module
- `parallel_http_runtime` remains a legitimate future split/size target, but it
is also the path that just delivered the latest shared-runtime performance win
- full-workspace release LLVM-lines still needs a non-MSVC or fixed
`cargo-llvm-lines` path before it should be treated as a strict gate
## Take 2 Reading
For Take 2, the honest conclusion is:
- size evidence now exists in-tree
- one real size-reduction tranche is now landed through the release profile
- the Rust host binary is now smaller than both the current C++ Pro Core and
the upstream Windows binary checked on this host
- the main size pressure comes from the combined RPC + HTTP/TLS stack, not from
one surprising internal crate explosion
- CLI-side LLVM IR now points at runtime execution and parallel HTTP scheduling
as the next owned code-size targets
- the latest CLI IR refresh still confirms the earlier config-projection and
shared-runtime cleanup reduced total CLI IR from `59,204` to `53,272` lines,
but the newest structural tree should now be treated as synchronized mainly
through the refreshed release build and `cargo bloat --crates` snapshot above
- deeper size reduction remains a future optimization lane, but the Phase 6
evidence set is now current enough to rank that work honestly
+22
View File
@@ -0,0 +1,22 @@
# Project Origins
`aria2-rust-pro` is an independently maintained Rust implementation. It uses
the following projects as explicit compatibility and migration references.
## Aria2-Pro-Core
[Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core) is the direct
reference for the enhanced deployment profile and migration expectations that
this project supports. Its behavior informs compatibility work; it is not this
repository's release source.
## aria2
[aria2](https://github.com/aria2/aria2) is the upstream download utility whose
CLI, configuration, RPC, and protocol contracts guide this implementation.
## Relationship
This repository has its own Rust codebase, release process, and issue tracker.
Compatibility claims describe the intended user-facing behavior; they do not
make this repository an official release of either reference project.
+305
View File
@@ -0,0 +1,305 @@
# Release Packaging and Local Deployment
This document covers the current local release workflow for `aria2-rust-pro`.
The scripts under `scripts/release/` cover three concrete needs:
- host-runnable `--version` smoke validation;
- deterministic local artifact naming plus SHA-256 generation;
- packaging of the current workspace's Windows or Linux release binary into a
ready-to-share archive.
- exporting a locally built Docker image tag into a portable tar archive under
`dist\docker\`.
As of the Phase 3 Cargo-native workflow push, the primary entrypoints now live
in `xtask/`. The PowerShell files under `scripts/release/` remain as thin
compatibility shims so existing local habits still work, but the canonical
project automation surface is now:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke-local
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke
```
These commands do not update `progress.md` or the compatibility ledger, and
they do not claim cross-host release certification by themselves. They are
local release helpers for the current workspace state.
## Files
- `xtask/`: canonical Cargo-native workflow entrypoints for release smoke and
local packaging.
- `scripts/release/smoke-version.ps1`: thin shim around
`xtask release smoke-version`.
- `scripts/release/package-local.ps1`: thin shim around
`xtask release package-local`.
- `scripts/docker/smoke-local.ps1`: thin shim around
`xtask docker smoke-local`.
- `scripts/docker/smoke.ps1`: thin shim around `xtask docker smoke`.
- `scripts/docker/export-local.ps1`: thin shim around
`xtask docker export-local`.
- `docs/release/RELEASE-NOTES-TEMPLATE.md`: reusable release-page and handoff
template for public-facing releases.
## Artifact naming
The package script emits archives named like:
- `aria2-rust-pro-v1.0.0-x86_64-pc-windows-msvc.zip`
- `aria2-rust-pro-v1.0.0-x86_64-unknown-linux-gnu.tar.gz`
The target triple always stays in the file name so mixed-host staging stays
unambiguous.
Output defaults to the workspace-level dist area:
```powershell
dist\release\v<version>\
```
Generated files per package run:
- the archive itself (`.zip` on Windows targets, `.tar.gz` otherwise);
- `<archive>.sha256`;
- `SHA256SUMS.txt`;
- `<artifact>.manifest.json`.
## Version smoke
From the repo root:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version
pwsh ./scripts/release/smoke-version.ps1
```
Build first, then smoke:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version --build
pwsh ./scripts/release/smoke-version.ps1 -Build
```
Smoke a specific binary:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release smoke-version --binary-path .\target\release\aria2-rust-pro.exe
pwsh ./scripts/release/smoke-version.ps1 -BinaryPath .\target\release\aria2-rust-pro.exe
```
The command succeeds only when the rendered banner keeps the upstream-compatible
first line `aria2 version 1.37.0` and also contains
`Rust rewrite package: aria2-rust-pro <workspace-version>`.
## Versioning and changelog
The workspace version in the root `Cargo.toml` is the source of truth. Release
tags must use `vMAJOR.MINOR.PATCH` and match that version. Preview the next
user-facing changelog entry with:
```powershell
rtk git-cliff --config .\cliff.toml --unreleased
```
For a release tag, a checked-in `docs/release/vX.Y.Z.md` remains authoritative.
When it is absent, the release workflow generates the Gitea release body from
`cliff.toml` and the Conventional Commit history.
On an actual release tag, the release workflow compares each public workspace
crate against the preceding SemVer tag with `cargo-semver-checks`. The first
release tag has no predecessor and therefore skips that comparison.
## Packaging the current host build
Build and package the host release binary:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build
pwsh ./scripts/release/package-local.ps1 -Build
```
Package an already-built host binary without rebuilding:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local
pwsh ./scripts/release/package-local.ps1
```
Write artifacts to a custom directory:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --output-root .\dist\release
pwsh ./scripts/release/package-local.ps1 -Build -OutputRoot .\dist\release
```
## Packaging Windows and Linux artifacts from the current workspace
### Windows host, Windows artifact
On the current Windows workspace, the default path uses:
- `target\release\aria2-rust-pro.exe`
- optional `target\release\aria2_rust_pro.pdb`
The archive is a `.zip` containing the binary, optional PDB, root `README.md`,
and the release packaging guide under `docs/release/README.md`. Version-specific
release notes such as `docs/release/v1.0.0.md` are used as Gitea release body
text, not bundled into every archive by default.
### Linux host, Linux artifact
On Linux with PowerShell 7 and Cargo available, the same script works:
```bash
pwsh ./scripts/release/package-local.ps1 -Build
```
The Linux archive format is `.tar.gz`, and the default packaged binary path is
`target/release/aria2-rust-pro`.
### Cross-target handling from one workspace
When the binary already exists under a target-specific Cargo directory, pass the
target triple:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --target-triple x86_64-pc-windows-msvc
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --build --target-triple x86_64-unknown-linux-gnu
pwsh ./scripts/release/package-local.ps1 -Build -TargetTriple x86_64-pc-windows-msvc
pwsh ./scripts/release/package-local.ps1 -Build -TargetTriple x86_64-unknown-linux-gnu
```
If the workspace cannot execute the packaged binary on the current host, package
the prebuilt file directly and skip the runtime smoke:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- release package-local --target-triple x86_64-unknown-linux-gnu --source-binary .\target\x86_64-unknown-linux-gnu\release\aria2-rust-pro --skip-version-smoke
pwsh ./scripts/release/package-local.ps1 `
-TargetTriple x86_64-unknown-linux-gnu `
-SourceBinary .\target\x86_64-unknown-linux-gnu\release\aria2-rust-pro `
-SkipVersionSmoke
```
That flow supports current-workspace staging for non-host artifacts, but the
runtime smoke must still be re-run on a compatible machine before calling the
artifact release-ready.
## Local deployment checklist
1. Unpack the archive to a clean directory.
2. Run the binary with `--version` and confirm the expected workspace version.
3. Compare the archive checksum with either `<archive>.sha256` or
`SHA256SUMS.txt`.
4. For container deployment, keep using the documented `docker/` workflow plus
`xtask docker smoke`, `xtask docker smoke-local`, or
`xtask docker export-local`. The matching `scripts/docker/*.ps1` files are
compatibility wrappers for those Cargo-native commands.
5. For direct CLI deployment, provide the same config/session/runtime paths you
already use for local compatibility testing.
## Exporting a local Docker image tar
When the Docker daemon is available and a local image exists or can be built:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker export-local --build
pwsh ./scripts/docker/export-local.ps1 -Build
```
That command writes a tar archive, checksum files, and a manifest under:
```powershell
dist\docker\v<version>\
```
The default tag is `aria2-rust-pro:local`. To export another tag:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker export-local --tag aria2-rust-pro:smoke
pwsh ./scripts/docker/export-local.ps1 -Tag aria2-rust-pro:smoke
```
## Docker smoke checks
After packaging or deployment changes, run the Cargo-native Docker smokes from
the repo root:
```powershell
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke-local
rtk cargo run --manifest-path .\xtask\Cargo.toml -- docker smoke --tag aria2-rust-pro:smoke
```
`xtask docker smoke-local` proves the entrypoint/config-generation path without
a Docker daemon. `xtask docker smoke` builds the image, starts a container,
checks generated config, and probes live JSON-RPC inside the running container.
The PowerShell scripts are compatibility wrappers around the same commands:
```powershell
pwsh ./scripts/docker/smoke-local.ps1
pwsh ./scripts/docker/smoke.ps1 -Tag aria2-rust-pro:smoke
```
The daemon-backed wrapper also forwards `-Build`, `-HostRpcPort`,
`-RpcSecret`, and `-SpecialMode` to the matching `xtask docker smoke` options.
## Self-hosted Gitea release verification
The self-hosted Gitea release workflow should be validated before cleaning up
old runner records in the Gitea UI. Keep runner cleanup as an infrastructure
follow-up, not part of the first release recovery step.
Use this order after CI has gone green on `main`:
1. Trigger the release workflow with `workflow_dispatch` and leave
`validation_only=true`, or run the equivalent release commands on the runner
host. Validation mode runs the release gates from the current ref and skips
Gitea publishing, so it can test the runner without mutating an existing
release.
2. Confirm the strict gate reaches the daemon-backed Docker smoke and that
`xtask docker smoke` completes its JSON-RPC probe.
3. Confirm `xtask docker export-local --build --tag aria2-rust-pro:release`
stages the Docker tar, manifest, and `SHA256SUMS.txt`.
4. For an actual tag-publish run, set `validation_only=false` or push a release
tag, then confirm `scripts/ci/publish-gitea-release.sh` can create or update
the Gitea release with all staged assets.
5. Only after the release workflow has passed, remove stale offline runner UI
records that no longer correspond to the active runner.
Do not delete the active runner registration while release validation is still
in progress. The current production runner identity should be confirmed from
the latest passing Gitea Actions run before any old offline entry is removed.
Do not move an already published tag just to validate the workflow; use the
default no-publish validation mode instead.
Recovered runner evidence:
- release validation run 107 passed on commit `6d4956b` with
`validation_only=true`;
- push CI run 108 passed on the same commit;
- the release validation spent roughly 720 seconds in fast gates and
784 seconds in strict gates, while checkout, tool bootstrap, release package,
and Docker export were short;
- no stale `GITEA-ACTIONS` containers or persisted temporary Gitea tokens should
remain after runner-side validation.
Treat those timings as a baseline when optimizing the self-hosted runner. Prefer
persistent Cargo registry/git cache or further runner-image prebaking before
target-directory caching, because target caches can be polluted by toolchain,
feature, and commit differences.
## Scope and remaining release limits
These scripts are the active local release helpers:
- they stage host artifacts and Docker image tar exports from the current
workspace;
- they do not, by themselves, certify that the current tree has reclosed every
reopened modernization phase;
- archived release records are preserved only as historical evidence under
`docs/archive/`;
- Docker image publication/signing still remains an external release-management
concern, while `export-local.ps1` and `xtask docker export-local` stage a
portable tar from the local daemon state under
`dist\docker\v<version>\`.
+69
View File
@@ -0,0 +1,69 @@
# aria2-rust-pro Release Notes Template
Use this template when cutting a public-facing release, local handoff package,
or Gitea release page.
---
## Summary
One short paragraph that answers:
- what this release is
- who should care
- whether this is mainly a feature release, compatibility release, packaging
release, or bugfix release
## Highlights
- highlight 1
- highlight 2
- highlight 3
## Compatibility Notes
- [aria2](https://github.com/aria2/aria2) baseline:
- [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core) behavior notes:
- Docker compatibility notes:
- RPC compatibility notes:
## Packaging
Artifacts included in this release:
- Windows:
- Linux:
- Docker image tar or image tag:
Checksums:
- `SHA256SUMS.txt` included: yes or no
- manifest files included: yes or no
## Migration Notes
Operator actions required before upgrade:
- config changes:
- compose or Docker env changes:
- host deployment changes:
- rollback considerations:
## Verification
Commands or evidence used to validate the release:
```text
list the exact commands run
```
## Known Limits
- limit 1
- limit 2
## Full Change List
- item
- item
- item
+71
View File
@@ -0,0 +1,71 @@
# aria2-rust-pro 1.0.0
`aria2-rust-pro 1.0.0` is the first public release of this independently
maintained Rust implementation.
This release establishes a versioned baseline for the project:
- a public Git tag for the Rust 2024 workspace
- Cargo-native local packaging and Docker export workflows
- repository-local migration, deployment, and compatibility documentation
## Project Sources
- [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core) is the direct
compatibility and migration reference for the enhanced deployment profile.
- [aria2](https://github.com/aria2/aria2) is the upstream project whose public
CLI, configuration, and RPC contracts guide this implementation.
## Highlights
- independently maintained Rust 2024 implementation informed by those sources
- Cargo-native release packaging and Docker export automation
- compatibility-led CLI, configuration, JSON-RPC, and XML-RPC development
## Compatibility Notes
- version smoke preserves the upstream-compatible first line
`aria2 version 1.37.0`
- Docker images keep the `aria2c` entrypoint shape by symlinking
`aria2c -> aria2-rust-pro`
- migration and deployment guides remain in-repo under `docs/migration/` and
`docs/deployment/`
## Artifacts
The release includes these built artifacts:
- `aria2-rust-pro-v1.0.0-x86_64-pc-windows-msvc.zip`: Windows x86_64 archive
with the executable, debug symbols, release documentation, a manifest, and
an individual SHA-256 checksum.
- `aria2-rust-pro-docker-v1.0.0.tar`: Linux amd64 Docker image archive tagged
`aria2-rust-pro:v1.0.0`, with a manifest and individual SHA-256 checksum.
- `RELEASE-SHA256SUMS.txt`: aggregate SHA-256 checksums for the two primary
archives.
Load the Docker archive with:
```sh
docker load -i aria2-rust-pro-docker-v1.0.0.tar
```
Verify an archive before use with its adjacent `.sha256` file or the aggregate
checksum list.
## Verification
The repository release workflow is intended to perform:
- workspace fast gates
- nightly `cargo udeps`
- `cargo deny`
- release version smoke
- daemon-free Docker smoke
- daemon-backed Docker smoke
- local release packaging
- Docker image export
## Known Limits
- Windows and Linux amd64 are the only prebuilt targets in this release
- broader multi-platform release archives remain future work
+147
View File
@@ -0,0 +1,147 @@
# Quality Gates
Primary test runner:
```powershell
rtk cargo nextest run --workspace --all-targets --all-features
```
Required final gates:
```powershell
rtk cargo fmt --all --check
rtk cargo check --workspace --all-targets --all-features --locked
rtk cargo nextest run --workspace --all-targets --all-features --locked
rtk cargo clippy --workspace --all-targets --all-features --locked --no-deps -- -D warnings -D clippy::pedantic -D clippy::nursery
rtk cargo +nightly udeps --workspace --all-targets --all-features --locked
rtk cargo deny --locked check
```
On this Windows host, `cargo deny` may inherit a broken Git `schannel` HTTPS
path and fail with `SEC_E_NO_CREDENTIALS`. The repository's strict sweep now
forces Git's `http.sslbackend=openssl` for the deny lane so the final gate does
not depend on ambient machine Git TLS settings.
If an `rtk` equivalent is unavailable or broken for a command, record the
fallback command in `progress.md`.
Recommended one-shot local sweep:
```powershell
pwsh ./scripts/testing/strict-sweep.ps1
```
## Self-Hosted Gitea Runner Notes
The self-hosted Gitea Actions runner image used for this repository must keep
`CARGO_BUILD_JOBS=2` for CI and release jobs. Do not lower it to `1` as a
generic resource-throttling tweak.
The fast gate runs `cargo clippy` across the workspace with strict lint levels.
On the NAS runner image, `CARGO_BUILD_JOBS=1` caused the clippy lane to stall in
a nested Cargo metadata / jobserver / target-lock chain. Keeping two build jobs
gives the nested Cargo process enough scheduling room while still bounding
runner load.
Do not add `-D clippy::cargo` back to CI or the local strict sweep without a
fresh runner-side validation pass. That lint group spawns nested
`cargo metadata` from clippy-driver, which can wait behind the parent
cargo/clippy target lock on this NAS runner. Dependency, license, and advisory
policy remains covered by the strict gate's `cargo deny` and `cargo udeps`
lanes.
The runner image should keep `cargo-nextest`, `cargo-deny`, and `cargo-udeps`
preinstalled. Baking those tools into the image reduced the `Install Cargo
tools` step from roughly 26 minutes to 0-1 seconds on the self-hosted runner.
Future image updates should preserve that tool cache before looking for more
invasive target-directory caching.
`docker/entrypoint.sh` must retain executable mode (`100755`) in Git. Linux
runner smokes execute it directly, and a non-executable checkout fails with
`Permission denied` before the entrypoint behavior is tested.
`xtask docker` defaults `DOCKER_BUILDKIT=0` when the caller has not set a
builder preference. Synology Docker 24 left buildx sessions idle on the full
release Dockerfile, while the classic builder completed the release image build
and export path. Override `DOCKER_BUILDKIT` only after testing the runner's
Docker daemon behavior.
Current runner timing evidence shows the remaining long steps are the Rust
quality gates themselves: cold registry/download work, Rust compilation,
nightly `build-std`, and NAS small-file IO. Docker image tar export was measured
around 20 seconds and was not the bottleneck in the recovered release run.
Keep the value aligned in both places:
- the runner image or image Dockerfile, such as
`/volume1/docker/gitea/runner-images/aria2-rust-1.88/Dockerfile`;
- `.gitea/workflows/ci.yml` and `.gitea/workflows/release.yml`.
If a future CI run appears stuck rather than failing with a compiler or test
error, check this before changing source code:
```bash
docker logs --tail 300 gitea-runner
docker inspect gitea-runner --format '{{json .Config.Env}}' | jq .
```
## CLI/tests/docs slice fallback lane
When lower-layer workspace crates are still red on strict docs or pedantic
lint, the CLI/tests/docs owner should still keep the owned surface ready for
final closeout with slice-scoped verification against the alternate target
directory:
```powershell
$env:CARGO_TARGET_DIR='.\target-alt'
rtk cargo check -p aria2-rust-pro-cli -p aria2-rust-pro-tests --all-targets
rtk cargo test -p aria2-rust-pro-cli
rtk cargo test -p aria2-rust-pro-tests
rtk cargo bench -p aria2-rust-pro-tests --bench rpc_pressure --no-run
rtk rustfmt --check crates/aria2-rust-pro-cli/src/lib.rs crates/aria2-rust-pro-cli/src/main.rs crates/aria2-rust-pro-tests/src/lib.rs crates/aria2-rust-pro-tests/benches/rpc_pressure.rs
rtk cargo clippy -p aria2-rust-pro-cli -p aria2-rust-pro-tests --all-targets --no-deps -- -D warnings -D clippy::pedantic
```
Notes for this lane:
- `cargo clippy --no-deps` is still useful for owned-file cleanup, but if
workspace-path dependencies fail before the CLI/tests targets are linted,
record the exact blocker in `progress.md` instead of widening the edit scope.
- `rustfmt` is file-scoped here on purpose so the lane can avoid touching
unrelated crates while another worker is active elsewhere in the workspace.
## Compatibility Evidence Slice
Lane F extends the integration suite in
`crates/aria2-rust-pro-tests/src/lib.rs` with representative RPC parity checks
that do not modify dispatcher or transport implementation files.
Recommended focused pass while iterating on RPC compatibility:
```powershell
rtk cargo test -p aria2-rust-pro-tests parsed_jsonrpc_change_option_request_shape_matches_manual_dispatch_state
rtk cargo test -p aria2-rust-pro-tests xmlrpc_and_jsonrpc
```
Representative coverage kept for compatibility relock work:
- Raw JSON-RPC request parsing drives the same downstream `aria2.changeOption`
state as a manually constructed request object.
- `aria2.getGlobalOption` returns the same object payload through JSON-RPC and
XML-RPC after option normalization.
- Filtered BitTorrent `aria2.tellStatus` responses keep the same request-shape
semantics and runtime field values across JSON-RPC and XML-RPC.
- `system.multicall` preserves nested result structure consistently across both
RPC front doors for mixed payloads such as version, session, and BT status.
- Invalid-GID failures keep the same underlying RPC error message across
JSON-RPC and XML-RPC, with XML-RPC still wrapping it in the upstream-style
fault envelope.
Remaining scope limits for this lane:
- These tests prove in-process request/response parity, not socket-level server
transport framing.
- XML-RPC number coercion is only covered where aria2-style payloads are
expected to round-trip through the shared `RpcValue` surface.
- Full dispatcher internals, router behavior, and transport implementations are
intentionally left to the lanes that own those files.