Repository navigation
[REA-6846] Answer data-channel chunking with reactor-webrtc 0.19 - #228
Merged
douglaseel merged 4 commits intoOct 5, 2026
Merged
Conversation
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Dere-Wah
approved these changes
Oct 3, 2026
Dere-Wah
left a comment
Contributor
There was a problem hiding this comment.
Approving. I checked compatibility with older clients: the answer carries a=x-reactor-dc-chunking only when the offer declares it, so a client without chunking keeps the plain channel and its current limits. A newer client against a runtime without this change also stays plain, because libwebrtc drops the unknown line and the answer does not mirror it.
CI is red only because reactor-webrtc==0.19.0 is not on PyPI yet. It must be green, with uv.lock updated, before merge. Two non-blocking notes inline.
A data-channel message is capped at 256 KiB on a plain channel, and a send past libwebrtc's 16 MiB buffer closes the channel. reactor-webrtc 0.19 carries larger messages as frames on channels whose peers both declare a=x-reactor-dc-chunking. The runtime answers, so it mirrors that only for a client that asks, and every other client keeps the plain channel. WebRtcConfig gains dc_chunking, on by default. Like SPED it is process-wide: the media engine carries it and is built on the first connection. uv.lock moves to 0.19.0 once that release is on PyPI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Douglas Ferreira <douglaseel@gmail.com>
with_dc_chunking also raises SCTP's per-send burst for every data channel the engine creates, so dc_chunking=False on one connection does not restore the previous send timing. The field's documentation now says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Douglas Ferreira <douglaseel@gmail.com>
0.19.0 is on PyPI, so the lockfile resolves the pin and a locked install works from public artifacts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Douglas Ferreira <douglaseel@gmail.com>
douglaseel
force-pushed
the
douglas/rea-6846-reactor-runtime-enable-dc-chunking
branch
from
October 5, 2026 14:50
b55f0f0 to
20ccd70
Compare
0.19.1 is the patch release whose source falls back to the p10 libwebrtc prebuilt; the wheel the runtime installs already bundled it, so nothing changes here beyond keeping in step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Douglas Ferreira <douglaseel@gmail.com>
douglaseel
added a commit
to reactor-team/reactor-client-sdks
that referenced
this pull request
Oct 5, 2026
## Why A command is capped at 256 KiB, the most a plain data channel takes, and fails with `MESSAGE_TOO_LARGE` above that. reactor-webrtc 0.19 carries messages of up to 64 MiB as frames on channels where both peers declare `a=x-reactor-dc-chunking` in the SDP. It also raises dcsctp's `max_burst` from 4 to 256, so a 100 KB message takes about one round trip instead of five. The SDK sends the offer, so it's the side that has to ask. reactor-runtime answers as of reactor-team/reactor-runtime#228, and a runtime that doesn't answer keeps the plain channel and today's limit. ## What Changed - The workspace moves to reactor-webrtc 0.19. The FFI builds its factory with `with_dc_chunking(DcChunking::default())`, and `offer_config` asks for chunking alongside SNAP. - `max_message_bytes()` follows the negotiation. Once the data channel is chunked it reports this side's chunked limit (64 MiB); before the channel opens, or against a runtime without chunking, it reports the plain 256 KiB. The core still checks a command against it before sending. - Only the channel knows the runtime's advertised limit. A command above that is refused by `send()` with `DcSendError::TooLarge`, which now maps to the same `MessageTooLarge` rather than a generic transport error. A full send queue stays `TRANSPORT_ERROR`, because it clears as the queue drains, and a new code would mean a new error class in every SDK. - The two `let mut` channel bindings lose their `mut`, since 0.19's setters take `&self`. - CHANGELOG entries for C++, Python, Swift and Java. JS reaches WebRTC through reactor-wasm and the browser, which gets its own implementation in the next PR of this stack. There are no C ABI changes, and no SDK's public API changes. The only visible difference: against a runtime that negotiates chunking, a command above 256 KiB is sent. Channel close does not drain. A command's request waits for the runtime's reply, so a completed command has fully arrived; a close mid-request already aborts the request. ## Validation All local, against a build of the reactor-webrtc 0.19 stack (patched in through an uncommitted `[patch.crates-io]`): - New loopback tests in `reactor-ffi`. The transport offers and a reactor-webrtc peer stands in for the runtime: - against a chunking runtime, `max_message_bytes()` reports 64 MiB and a 1 MiB command arrives whole; - against a plain runtime, the limit stays 256 KiB. - Both passed in 3 out of 3 runs. - Unit tests cover the offer, the error mapping, and the limit before a connection exists. - `cargo test -p reactor-ffi -p reactor-core` passes (59 + 131), and `cargo clippy --all-targets -D warnings` is clean. `Cargo.lock` moves to 0.19 once it's on crates.io. Until then CI can't resolve the pin. Linear: [REA-6847](https://linear.app/reactor-team/issue/REA-6847) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor
Author
Merge activity
|
douglaseel
deleted the
douglas/rea-6846-reactor-runtime-enable-dc-chunking
branch
October 5, 2026 16:44
douglaseel
added a commit
that referenced
this pull request
Oct 5, 2026
…#240) ## Why Releases what has landed since 3.6.1. It adds new public surface and moves nothing on the wire, which makes it a minor release: - **Data-channel chunking** (#228–#230). `WebRtcConfig.dc_chunking` is on by default. The runtime answers clients that ask for chunked data channels, so a command or a model message of up to 64 MiB passes, instead of being capped at 256 KiB. Refused frames are logged once per channel, and a teardown sends what a chunked channel still has queued. A client that doesn't ask keeps the plain channel. - **Step sessions** (#231–#239): a session's starting input and step count on the start body, `complete_step()`, closing a session at its steps, the `runtime.step_results` manifest block, and step output saved as an MP4 or a folder of files, served over HTTP. - **Client stats** (#201, #224): client-observed WebRTC stats decoded in the transport and journaled as metric self-loops. - **reactor-webrtc 0.21.0** (from 0.19.1). - 0.21.0 keeps per-frame metadata on its own frame when libwebrtc drops a frame before render. Before, metadata was matched by queue order, so after a dropped frame every later frame got its predecessor's metadata. - It also keeps a `FrameTransform`'s `replace_data` through the metadata step. - 0.20.0 is additive. - Neither changes the Python API the runtime uses. - Dependency bumps (#216–#220). ## What Changed Two commits: - `uv version 3.7.0`, which updates the version in `pyproject.toml` and `uv.lock`; - `reactor-webrtc==0.21.0`, relocked. Only that package moves in `uv.lock`. Merging tags `v3.7.0` and publishes. Checked locally with a locked install of the published reactor-webrtc 0.21.0 wheel: - lint, typecheck and the HTTP spec check pass; - unit tests pass (1917); - integration tests pass (12). And with the release workflow's own gates: - `mise run http-breaking-release`: "3.6.1 -> 3.7.0 (minor) satisfies the mandated patch"; - `mise run wire-check-release`: the pin matches `proto/`; - `mise run build`: builds the 3.7.0 wheel and sdist. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Why
A plain data channel takes messages of up to 256 KiB, and a send past libwebrtc's 16 MiB buffer closes the channel. The runtime has both limits in each direction: a client can't send a command or a frame larger than 256 KiB, and a result above 16 MiB can't be sent at all. reactor-webrtc 0.19 lifts both on channels where both peers declare
a=x-reactor-dc-chunkingin the SDP. Messages travel as frames of a few KiB, and up to 64 MiB passes in either direction. dcsctp'smax_burstalso goes from 4 to 256, so a 100 KB message takes about one round trip instead of five.The runtime answers the offer, so it mirrors the attribute only for a client that declares it. A client that doesn't keeps the plain channel and its limits. That makes it safe to ship ahead of the SDKs that will ask for it.
What Changed
WebRtcConfiggainsdc_chunking, on by default, following the WARP pattern:Like SPED, it's process-wide: the media engine carries it and is built on the first connection, so the first connection's value is the one the process keeps. The field's documentation says so. A connection built with
Falseon an engine that has chunking keeps plain channels.The pin moves to
reactor-webrtc==0.19.0.uv.lockfollows once 0.19.0 is on PyPI. Until then, every job that installs from the lock fails (including the mise-lock script tests, which resolve the project).Validated locally against a build of the 0.19 API:
🤖 Generated with Claude Code