joule-contrib: an SRT sender probes a stalled tail, so a lost newest packet is recovered #503

Merged
dcharlot merged 2 commits from fix/srt-close-after-drain into main 2026-10-26 22:57:27 -04:00
Owner

What

An SRT sender now probes a stalled tail. Live-contribution §4.1 and the changelog say so.

A receiver finds a gap only when a later packet arrives. So if the newest packet is lost, nothing asks for it, and the sender held it until it expired. CI's linux-arm64 leg failed an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt on #499 this way.

When the acknowledged position has not moved for 2 × RTT + 20 ms, and the newest packet held went out that long ago, the sender sends that packet again with the R flag set. The wait doubles with each probe, to at most 16 times the first, and resets when an ACK removes a packet.

SendCounts gains two fields:

  • probes, counted separately from retransmitted, which still means retransmissions in answer to requests;
  • unacknowledged, for SRT only.

The test now closes the publisher once nothing is unacknowledged. It also requires expired == 0, and its end-code assertion prints the code it read.

Evidence (Framework box, x86_64 Linux)

Run Result
main, four instances at once on two cores 4 of 32 failed: the gateway's parts covered 107 of the 108 sequence numbers sent, and the sender read expired: 1
main, alone or four at once without pinning 60 of 60 passed
this branch, four at once on two cores 48 of 48 passed
this branch with the probe disabled (falsification) 2 of 24 failed with the same signature

The job's own commands all pass:

Command Tests
cargo test -p joule-contrib --all-targets 30
the same with --features rist 43
cargo test -p joule-moq-ingest --all-targets 73
the same with --features rist 75

The link-vector corpus check passes (101 files). Clippy reports nothing in the changed files. The comparative-prose, vanity, spec-refs and section-refs checks pass.

🤖 Generated with Claude Code

## What An SRT sender now probes a stalled tail. Live-contribution §4.1 and the changelog say so. A receiver finds a gap only when a later packet arrives. So if the newest packet is lost, nothing asks for it, and the sender held it until it expired. CI's linux-arm64 leg failed `an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt` on #499 this way. When the acknowledged position has not moved for 2 × RTT + 20 ms, and the newest packet held went out that long ago, the sender sends that packet again with the R flag set. The wait doubles with each probe, to at most 16 times the first, and resets when an ACK removes a packet. `SendCounts` gains two fields: - `probes`, counted separately from `retransmitted`, which still means retransmissions in answer to requests; - `unacknowledged`, for SRT only. The test now closes the publisher once nothing is unacknowledged. It also requires `expired == 0`, and its end-code assertion prints the code it read. ## Evidence (Framework box, x86_64 Linux) | Run | Result | |---|---| | main, four instances at once on two cores | 4 of 32 failed: the gateway's parts covered 107 of the 108 sequence numbers sent, and the sender read `expired: 1` | | main, alone or four at once without pinning | 60 of 60 passed | | this branch, four at once on two cores | 48 of 48 passed | | this branch with the probe disabled (falsification) | 2 of 24 failed with the same signature | The job's own commands all pass: | Command | Tests | |---|---| | `cargo test -p joule-contrib --all-targets` | 30 | | the same with `--features rist` | 43 | | `cargo test -p joule-moq-ingest --all-targets` | 73 | | the same with `--features rist` | 75 | The link-vector corpus check passes (101 files). Clippy reports nothing in the changed files. The comparative-prose, vanity, spec-refs and section-refs checks pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt closed the
publisher a fixed 800 ms after its last frame. On a loaded host a loss on the
3%-lossy path was still unrecovered then: the gateway counted 107 of 108
payloads delivered and one outstanding (4 failures in 32 runs, four at a time
on two cores; CI's linux-arm64 leg failed it on #499). The sender now keeps
`SendCounts::unacknowledged` (SRT; RIST acknowledges nothing and leaves it 0),
and the test closes once it is 0. The end-code assertion now says which code
it read.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
joule-contrib: an SRT sender probes a stalled tail; live-contribution §4.1 says so
All checks were successful
WAI conformance / does this change touch it (pull_request) Successful in 8s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 10s
WAI energy receipts / does this change touch it (pull_request) Successful in 9s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (pull_request) Successful in 35s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 18s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 28s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 31s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m8s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m54s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m24s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m54s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 3m15s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m19s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 3m26s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 26s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 43s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 5m56s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m14s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m39s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 9m54s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m22s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 10m39s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m54s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 14m44s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 9m7s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 17m33s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 17m58s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 54m3s
1fd0322436
A receiver finds a gap only behind a later arrival, so a lost newest packet
went unrecovered until the sender expired it. Under contention (four at a
time on two cores) an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt
failed 4 of 32 and 17 of 48: the sender's counts read expired=1 and the
gateway's parts covered 107 of the 108 sequence numbers sent. CI's
linux-arm64 leg failed the same test on #499.

When the acknowledged position has not moved for 2 x RTT + 20 ms and the
newest packet held went out that long ago, the sender sends it again with
the R flag, the wait doubling per probe to 16 times the first, reset when an
ACK takes a packet. SendCounts::probes counts them apart from retransmitted,
which answers requests. The test now also requires that the publisher gave
nothing up (expired == 0).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!503
No description provided.