Return a PublishDataInstruction from PublishData#301
Open
MaxHeimbrock wants to merge 4 commits into
Open
Conversation
LocalParticipant.PublishData is fire-and-forget — the C# API has no callback, so server-side drops of oversized packets are silent. These tests probe the boundary empirically by publishing payloads of varying sizes between two participants and asserting delivery via the subscriber's DataReceived event. Retries on a 200 ms interval to avoid SFU warm-up flakiness. Verified against livekit-server 1.12.0: 1 KiB and 15 KiB arrive intact (length + bytes); 65 KiB is dropped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PublishData was fire-and-forget (void), so callers could not tell whether
the Rust side accepted the packet. The FFI transport already carried the
result end-to-end — PublishDataRequest has a request_async_id, Rust emits
a PublishDataCallback { async_id, error }, and the data_task forwards the
publish result into it — but the C# side discarded the event.
Wire it through:
- New PublishDataInstruction (YieldInstruction) exposing IsError + Error.
- The three PublishData overloads now return it instead of void
(source-compatible: callers ignoring the result still compile).
- Route the callback by adding PublishData to FFIClient.ExtractRequestAsyncId.
Packets over the negotiated maximum message size now surface the error
("data packet size (N bytes) exceeds the negotiated maximum message size
(64000 bytes)") via instruction.Error.
Tests: ReturnsSuccess_ForSmallPayload verifies the success path on any
binary. ReturnsError_ForOversizedPayload (Explicit) verifies the size-limit
error and requires the client-sdk-rust datamessage_size FFI binary.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
xianshijing-lk
approved these changes
Jun 11, 2026
xianshijing-lk
left a comment
Contributor
There was a problem hiding this comment.
some nits / questions
| /// Check <see cref="YieldInstruction.IsError"/> and read <see cref="PublishDataInstruction.Error"/> | ||
| /// to handle the result (e.g. payloads exceeding the negotiated maximum message size). | ||
| /// </returns> | ||
| public PublishDataInstruction PublishData(byte[] data, IReadOnlyCollection<string> destination_identities = null, bool reliable = true, string topic = null) |
Contributor
There was a problem hiding this comment.
Instruction does not seem to be a common technology for such purpose ?
how about PublishDataTask ?
Contributor
Author
There was a problem hiding this comment.
We use the instruction term since the base type is CustomYieldInstruction
Other examples in our code base:
Contributor
Author
There was a problem hiding this comment.
Instructions use Coroutines underneath, Tasks use C# async
| IsDone = true; | ||
| } | ||
|
|
||
| void OnCanceled() |
Contributor
There was a problem hiding this comment.
nit, should onCanceled() private ?
Contributor
Author
There was a problem hiding this comment.
It is private by default, and we also use the implicit private style around in the other instruction classes:
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.
Dependency
Depends on livekit/rust-sdks#1137
Fails without: https://github.com/livekit/client-sdk-unity/actions/runs/27275793150
Summary
LocalParticipant.PublishDatawas fire-and-forget (void), so callers had no way to know whether the Rust side accepted the packet — most importantly, packets exceeding the negotiated maximum message size were dropped with only alog::warn!.This wires through the result the FFI transport already carried (no proto regen, no Rust changes):
PublishDataRequestalready hasrequest_async_id; Rust already emitsPublishDataCallback { async_id, error }anddata_taskforwards the publish result into it. The C# side simply discarded the event.Changes:
PublishDataInstruction(YieldInstruction) exposingIsError+Error.PublishDataoverloads now return it instead ofvoid(source-compatible — callers ignoring the result still compile).PublishDatatoFFIClient.ExtractRequestAsyncId.Oversized packets now surface the error via
instruction.Error:Tests
ReturnsSuccess_ForSmallPayload— verifies the success path; runs on any FFI binary.ReturnsError_ForOversizedPayload— verifies the size-limit error. Marked[Explicit]: it requires theclient-sdk-rustdatamessage_sizeFFI binary that enforces the 64000-byte limit (shipped plugins do not yet). Against the old binary an oversized reliable send wedges the publisher transport instead of returning cleanly — which is the behavior the limit fixes.Verified locally: all 2
PublishDataTestspass (3.3s) against a macOS FFI lib rebuilt fromdatamessage_size+livekit-server --dev.