Skip to content

feat(net): negotiate IETF compressed tracks from draft17 - #6228

Merged
kixelated merged 10 commits into
mainfrom
quest/m1/compress/ietf
Oct 22, 2026
Merged

kixelated merged 10 commits into
mainfrom
quest/m1/compress/ietf

Conversation

@kixelated

@kixelated kixelated commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

track::Info::compress already stores compressed groups, but IETF sessions inflate every track before sending it. The current consumer is moq-relay forwarding repetitive JSON/catalog, statistics, and timeline tracks between Rust IETF peers, or from an IETF publisher to lite-07 subscribers.

Approach

Negotiate FLATE on draft 17 and later and carry a known COMPRESSION track property plus each object's INFLATED_SIZE. Subgroups, FETCH, datagrams, and the PUBLISHes answering SUBSCRIBE_TRACKS preserve their stored compressed form. Missing or inconsistent size declarations fail before inflated output escapes the existing model bounds.

Draft 14 through 16 retain plain delivery and their existing TRACK_STATUS/FETCH behavior. Peers without FLATE receive the shared inflated copy. Immutable declarations remain byte-for-byte sealed; delivery is refused whenever plain fallback or another property encoding cannot preserve them. Status objects refuse inflated-size declarations, including sealed ones.

Update the feature draft and protocol guide, remove the completed child quest, and retain the parent epic's independent JS/migration work.

Impact

  • Public API: no new package API or breaking shape. The existing track::Info::compress flag now applies to negotiated IETF sessions.
  • Wire: additive FLATE (0x40B6A), COMPRESSION (0x40B6C), and INFLATED_SIZE (0x40B6E) on draft 17+. The draft documents the format and registrations. Published legacy versions keep their plain behavior.
  • JS does not offer IETF FLATE. A new cross-language regression uses its real setup builder and subscriber to consume Rust's plain fallback on draft 17 and 22, with no new JS API.

Validation:

  • Full moq-net suite after merging main: 2,909 passed (nextest; hardware and explicit interop tests skipped). The new interop test passes separately.
  • A new malformed-status regression fails before the fix and passes afterward; focused compression/fetch-only tests pass, including both prior draft 16 failures.
  • Merging main brought SUBSCRIBE_TRACKS (moq-dev/moq#6167); its listed PUBLISHes now declare and serve compression from the negotiated option. a_publish_compresses_only_when_negotiated covers drafts 18-22 and fails without the fix.
  • just drafts check, just test interop --all, and the new ietf_compression_fallback_interop pass. The new test is wired into just test interop.
  • just check passes lint, docs, clippy, wasm, and JS. Its flake module cannot build the runner image on this host (unshare: write failed /proc/self/uid_map), so the merge queue's gate is the authority for that step.
  • The checked-in session_delivery_compression benchmark completed all 12 cases: publishers 1/16 × viewers 1/16, four 1024-byte frames, lite06 plain fallback, lite07 and IETF22. Reproduce with cargo bench --locked -j 2 -p moq-net --bench session -- session_delivery_compression --sample-size 10 --measurement-time 1 --warm-up-time 1 --noplot in the Nix shell.
Protocol 1 publisher, 1 viewer 1,16 16,1 16,16
lite06 plain fallback 57.34µs 310.07µs 48.99µs 856.70µs
lite07 53.53µs 368.70µs 53.02µs 930.47µs
IETF22 51.55µs 371.96µs 52.39µs 950.11µs

These are single-host samples with background CI/load 20–29. Criterion's shared historical cache reported +14.2% for the IETF22 case with 16 publishers and 16 viewers against an earlier run; that comparison is uncontrolled and does not establish a source-level regression or improvement.

Alternatives

Draft16 compression would require changing its existing TRACK_STATUS/SUBSCRIBE behavior or inventing old-version fields. The maintainer chose draft 17+ instead. Removing sealed declarations for fallback would violate the settled immutable-property contract, so those incompatible deliveries are refused.

Follow-ups

No new scope or API decisions. The existing parent epic owns JS lite-07 compression, consumer migration, and the end-to-end guide.

(Written by GPT-6, updated by Claude Opus 5.5)

kixelated and others added 8 commits October 21, 2026 15:14
Co-Authored-By: GPT-6 <noreply@openai.com>
Checkpoint only: no compression capability is advertised and track/object behavior is unchanged. Four focused codec/peer tests pass through just rs test; full CI, drafts and interop remain for the complete implementation.

Blocked on policy for compression declarations inside Immutable Properties: mutable-only declarations preserve unconditional plain fallback; allowing sealed declarations requires refusing or weakening fallback. Do not implement either until the maintainer decides.

Co-Authored-By: GPT-6 <noreply@openai.com>
Co-Authored-By: GPT-6 <noreply@openai.com>
Implement the approved sealed-property refusal policy and bounded stored-form object admission. Focused compression regressions pass across negotiated IETF and lite relay paths. Draft16 TRACK_STATUS cannot carry compression metadata: forcing SUBSCRIBE regresses existing fetch-only guarantees, so its query signaling needs a maintainer decision before publication. No new wire shape is chosen for that gap.

Co-Authored-By: GPT-6 <noreply@openai.com>
Focused compression tests: 43 passed. Draft rendering and cross-language interop --all passed. Full moq-net: 2870 passed, two draft16 fetch-only failures, eight skipped. CI stops at the unchanged runner-image user-namespace restriction. The publisher/viewer benchmark grid completed.

The temporary base fixture overlay is restored and excluded. Keep this checkpoint local until the maintainer chooses a negotiated Track Properties parameter, trailing block, or support beginning at draft17.

Co-Authored-By: GPT-6 <noreply@openai.com>
Preserve legacy query and plain fallback behavior, refuse sealed declarations that cannot be preserved, and verify the real JS offer and subscriber consume inflated fallback.

Co-Authored-By: GPT-6 <noreply@openai.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Implemented the settled draft 17+ extension, retaining draft 14 through 16 plain delivery and fetch-only behavior. Immutable compression declarations are preserved or refused when fallback cannot preserve them. No public API choice remains.

Validation: 2,874 moq-net tests, draft checks, full cross-language interop, and the targeted real-JS-handshake/subscriber fallback regression pass. The checked-in compression fanout benchmark completed all 12 lanes; results and its background-load limitation are in the description. just ci reached the unchanged runner-image uid_map: Operation not permitted failure, so this remains draft for the required gate.

The source is committed and pushed at d898c7b. The worktree is preserved, with no background process left running. No new follow-up quest is proposed; the existing compression epic retains JS, migration, and guide work.

(Written by GPT-6)

kixelated and others added 2 commits October 21, 2026 23:04
# Conflicts:
#	quest/m1/compress/README.md
#	test/justfile
The SUBSCRIBE_TRACKS publisher from main declares a listed track's properties and
serves resumed PUBLISHes; both now follow the negotiated FLATE option, so a
compressed track is declared and sent compressed only to a peer that offered it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 22, 2026 06:32
@coderabbitai

coderabbitai Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 11 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 499d5220-3899-4d7c-bd36-436f39bb6b73
📥 Commits

Reviewing files that changed from the base of the PR and between bce217e and 7f23715.

📒 Files selected for processing: 27
  • doc/concept/standard.md
  • drafts/draft-lcurley-moq-flate.md
  • quest/m1/compress/README.md
  • quest/m1/compress/ietf.md
  • rs/moq-net/benches/session.rs
  • rs/moq-net/src/client.rs
  • rs/moq-net/src/ietf/flate.rs
  • rs/moq-net/src/ietf/mod.rs
  • rs/moq-net/src/ietf/object.rs
  • rs/moq-net/src/ietf/parameters.rs
  • rs/moq-net/src/ietf/peer.rs
  • rs/moq-net/src/ietf/properties.rs
  • rs/moq-net/src/ietf/publish.rs
  • rs/moq-net/src/ietf/publisher.rs
  • rs/moq-net/src/ietf/publisher/tracks.rs
  • rs/moq-net/src/ietf/session.rs
  • rs/moq-net/src/ietf/subscribe.rs
  • rs/moq-net/src/ietf/subscriber.rs
  • rs/moq-net/src/ietf/track.rs
  • rs/moq-net/src/ietf/version.rs
  • rs/moq-net/src/lite/publisher.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/src/server.rs
  • rs/moq-net/src/test_interop.rs
  • rs/moq-net/tests/integration/compress.rs
  • test/interop/ietf-compression.ts
  • test/justfile
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-22T06:39:06.128232Z 7f23715 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f2371589f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +215 to +216
if compression {
group = group.compressed();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject partial FETCHes before serving compressed slices

When a negotiated FLATE FETCH starts at a nonzero object, frame_start is set to skip for a locally cached group and this switches that suffix directly to its stored compressed form. Every slice after object 0 was encoded using the preceding objects' DEFLATE window, so a receiver starting with this first returned slice cannot decompress it; the response is therefore unusable or malformed. Read from object 0 when compression is selected, or refuse a range that omits the compressed prefix.

AGENTS.md reference: rs/moq-net/AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declining this one. A FETCH that starts mid-group is how a consumer completes a group whose compressed head it already holds: the Rust IETF subscriber's run_group_fetch asks from the reader's frame_start to fill a cache miss, and model::resume stitches that suffix onto the head (a_failed_compressed_group_continues_from_the_replacement). Reading from object 0 would return objects outside the requested range, and refusing would break that continuation. lite-07 FETCH serves start_frame onward compressed for the same reason.

A consumer without the prefix is covered by the draft: "A consumer missing an object MUST abandon the rest of the subgroup", and the Rust model fails the read (a_compressed_group_without_its_head_fails_the_read) rather than emitting garbage.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit 7ec8dc2 Oct 22, 2026
12 checks passed
@kixelated
kixelated deleted the quest/m1/compress/ietf branch October 22, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant