diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9fd52..e5ae533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,61 @@ All notable changes to this crate are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this crate adheres to [Semantic Versioning](https://semver.org/). +## [0.10.1] - 2026-10-22 + +The adoption-window ordering fix (review 013, routed from alkgit's +wave-2 gate): a chunk routed by the demux inside the +`adopt_channel` install→drain window was delivered **ahead of** +earlier-parked early arrivals, inverting the channel's byte-stream +order (observed downstream as two distinct pkt-line desync shapes in +alkgit's open-op integration test under multi-process load — failure +shape 1, the reader starting mid-advertisement at offset ~16; failure +shape 2, a chunk boundary two bytes into a hex-length header). A +related loss variant is also closed: a chunk whose map miss parked it +after the drain had removed the queue sat parked forever, invisible to +`dropped_unknown_chunks`. No API, wire-format (`EventEnvelope`, the +channels 8-byte chunk header), or documented-cap behavior (review 006 +E-04) change — `ChannelState` and the fix surface are private; the +behavior only strengthens. + +### Fixed + +- **The adopt-window ordering race (review 013 C-01).** The install + and its park-drain are now one atomic section. `route_payload`'s + map-miss → early-arrival-park decision runs under the channels-map + lock (a park can never straddle the install — closing the orphaned + chunk loss variant), and the new private `install_locked` helper + (shared by `open_channel` / `adopt_channel` / + `install_channel_zero`) swaps the parked queue out, inserts the + state, and `try_send`s the parked queue into the fresh, empty + receiver **before releasing the lock** — a direct route (map hit) + can only begin after release, so parked chunks always precede it in + mpsc send order and the reassembled byte stream preserves + wire-arrival order through the adoption window. No await runs inside + the section: the effective park cap is + `min(EARLY_ARRIVAL_CAP, buffer_cap)`, bounding the parked queue by + the receiver's capacity so the non-blocking drain always fits + (smaller `buffer_cap` values tighten the park cap; the default + 64/64 pairing is unchanged). `drain_early_arrivals` remains as the + defensive full-buffer fallback, now called by all three install + paths. Regression tests: + `adopt_window_does_not_reorder_chunks` (200 iterations on a real + 2-worker runtime — a racer routing a chunk the moment the install + becomes visible; the receiver's byte stream must be byte-identical + to the producer's every time, the alkgit repro shape), + `adopt_drains_parked_and_raced_chunks_in_fifo`, and + `park_cap_bounded_by_receiver_buffer`. Downstream gate: alkgit's + flaking row re-verified green under multi-process load against this + fix before the 0.10.1 publish. + +### Verified + +- 700 tests pass (including the stub guard; 724 with `--all-features`); + `clippy --all-targets -- -D warnings`, `fmt --check`, `cargo doc`, + wasm32-unknown-unknown check, fuzz corpus replay + (`cargo test --manifest-path fuzz/shared/Cargo.toml`), + `cargo semver-checks`, and `cargo publish --dry-run` clean. + ## [0.10.0] - 2026-10-17 The gateway ownership seam (review 012, downstream evidence from diff --git a/Cargo.lock b/Cargo.lock index 0ccd2af..171c18d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "alkcall" -version = "0.10.0" +version = "0.10.1" dependencies = [ "async-trait", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 8036d3a..c2117c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alkcall" -version = "0.10.0" +version = "0.10.1" edition = "2021" rust-version = "1.88" license = "MIT OR Apache-2.0" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 1370d44..306b45f 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "alkcall" -version = "0.10.0" +version = "0.10.1" dependencies = [ "async-trait", "bytes",