Skip to content

Conversation

@xianshijing-lk
Copy link
Contributor

@xianshijing-lk xianshijing-lk commented Jan 19, 2026

This PR will allows client SDKs to generate an async id for the async requests, and start a listener before passing the requests, so that it could fix the race conditions.

Summary by CodeRabbit

  • New Features
    • Added optional request correlation identifiers to asynchronous operations across audio capture, data streaming, room management, RPC, and track statistics, enabling clients to better track and match requests with their corresponding responses.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 19, 2026

📝 Walkthrough

Walkthrough

This PR extends FFI protocol messages with an optional request_async_id field to enable request-response correlation. The server implementation is updated to resolve provided IDs instead of generating new ones, allowing clients to track async operations.

Changes

Cohort / File(s) Summary
Protocol Buffer Definitions
livekit-ffi/protocol/audio_frame.proto, data_stream.proto, room.proto, rpc.proto, track.proto
Added optional uint64 request_async_id field to request messages across all protocols. Audio frame adds field 3; data stream requests use fields 2, 3, or 4 depending on message; room requests use fields 2–8; RPC uses field 6; track uses field 2. No changes to response or callback messages.
Server Core
livekit-ffi/src/server/mod.rs
New public method resolve_async_id() introduced. Returns provided request_async_id if present, otherwise generates new ID via next_id().
Audio & Stream Handlers
livekit-ffi/src/server/audio_source.rs, data_stream.rs
Replaced server.next_id() with server.resolve_async_id(request.request_async_id) in capture and stream operations. Parameter renamed from _request to request in read\_all methods to enable ID resolution.
Participant & Request Handlers
livekit-ffi/src/server/participant.rs, requests.rs
Updated async ID generation to use resolve_async_id() across RPC, stream, stats, and disconnect operations. Callbacks now reference resolved request IDs instead of freshly generated ones.
Room Operations
livekit-ffi/src/server/room.rs
Applied resolve_async_id() to connect, publish, metadata, chat, and stream operations. Added field cloning in publish operations (topic, destination_identities, digit) to maintain ownership when reusing request values.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant FfiServer
    participant AsyncTask as Async Handler

    Note over Client,AsyncTask: New Flow: Request Correlation

    Client->>FfiServer: Request with request_async_id = 42
    FfiServer->>FfiServer: resolve_async_id(42) → 42
    FfiServer->>AsyncTask: Spawn task with async_id = 42
    AsyncTask->>AsyncTask: Execute operation
    AsyncTask->>FfiServer: Emit callback(async_id = 42)
    FfiServer->>Client: Send callback with id = 42

    Note over Client,AsyncTask: Old Flow: Auto-Generated IDs

    Client->>FfiServer: Request
    FfiServer->>FfiServer: next_id() → 99
    FfiServer->>AsyncTask: Spawn task with async_id = 99
    AsyncTask->>AsyncTask: Execute operation
    AsyncTask->>FfiServer: Emit callback(async_id = 99)
    FfiServer->>Client: Send callback with id = 99
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Poem

🐰 A hop through async flows so true,
Request IDs now journey through,
From client to callback they trace,
Each response finds its rightful place!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: adding a request_async_id field to async requests across multiple protocol files and updating the server implementation to use these IDs.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
livekit-ffi/src/server/mod.rs (1)

182-186: Consider documenting the ID collision risk and expected client behavior.

The implementation is straightforward and achieves the stated goal of allowing clients to pre-register listeners before sending requests. However, there's a potential risk: if a client provides a request_async_id that happens to collide with a server-generated ID (from next_id()), callbacks could be misrouted.

Since the server generates IDs starting from 1 and incrementing, consider:

  1. Documenting that clients should use IDs from a non-overlapping range (e.g., high bit set), or
  2. Reserving a range of IDs for client use vs server use

If this is already handled at the protocol/client SDK level, a brief doc comment here would help future maintainers understand the expected contract.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2975ff4 and fb3e47d.

📒 Files selected for processing (11)
  • livekit-ffi/protocol/audio_frame.proto
  • livekit-ffi/protocol/data_stream.proto
  • livekit-ffi/protocol/room.proto
  • livekit-ffi/protocol/rpc.proto
  • livekit-ffi/protocol/track.proto
  • livekit-ffi/src/server/audio_source.rs
  • livekit-ffi/src/server/data_stream.rs
  • livekit-ffi/src/server/mod.rs
  • livekit-ffi/src/server/participant.rs
  • livekit-ffi/src/server/requests.rs
  • livekit-ffi/src/server/room.rs
🧰 Additional context used
🧬 Code graph analysis (2)
livekit-ffi/src/server/audio_source.rs (1)
livekit-ffi/src/server/requests.rs (16)
  • server (70-70)
  • server (87-87)
  • server (98-98)
  • server (110-110)
  • server (121-121)
  • server (133-133)
  • server (144-144)
  • server (159-159)
  • server (174-174)
  • server (189-189)
  • server (207-208)
  • server (219-219)
  • server (228-229)
  • server (239-240)
  • server (250-251)
  • server (261-262)
livekit-ffi/src/server/data_stream.rs (1)
livekit-ffi/src/server/requests.rs (16)
  • server (70-70)
  • server (87-87)
  • server (98-98)
  • server (110-110)
  • server (121-121)
  • server (133-133)
  • server (144-144)
  • server (159-159)
  • server (174-174)
  • server (189-189)
  • server (207-208)
  • server (219-219)
  • server (228-229)
  • server (239-240)
  • server (250-251)
  • server (261-262)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test (x86_64-pc-windows-msvc)
  • GitHub Check: Test (x86_64-unknown-linux-gnu)
  • GitHub Check: Test (x86_64-apple-darwin)
🔇 Additional comments (49)
livekit-ffi/protocol/track.proto (1)

42-48: LGTM!

The addition of optional uint64 request_async_id = 2 to GetStatsRequest follows the established pattern in this PR. The optional nature ensures backward compatibility—clients that don't provide the field will receive server-generated IDs, while clients that do can correlate responses before the request is issued.

livekit-ffi/protocol/audio_frame.proto (1)

59-72: LGTM!

The request_async_id field addition to CaptureAudioFrameRequest is consistent with the PR's pattern. Field number 3 correctly follows the existing fields, and the optional type maintains backward compatibility.

livekit-ffi/protocol/data_stream.proto (6)

38-51: LGTM!

The request_async_id additions to the text stream reader requests are consistent with the PR pattern.


84-97: LGTM!

The request_async_id additions to byte stream reader requests are correctly placed and follow the established pattern.


100-123: LGTM!

The ByteStreamReaderWriteToFileRequest correctly includes request_async_id as field 2, with subsequent fields properly numbered.


144-211: LGTM!

The StreamSendFileRequest, StreamSendBytesRequest, and StreamSendTextRequest messages all correctly add request_async_id as field 4, following the existing required fields.


222-267: LGTM!

The byte stream writer request messages (ByteStreamOpenRequest, ByteStreamWriterWriteRequest, ByteStreamWriterCloseRequest) correctly add request_async_id with appropriate field numbers.


278-323: LGTM!

The text stream writer request messages (TextStreamOpenRequest, TextStreamWriterWriteRequest, TextStreamWriterCloseRequest) correctly add request_async_id with appropriate field numbers, completing the consistent pattern across all data stream operations.

livekit-ffi/protocol/room.proto (8)

29-37: LGTM!

The ConnectRequest correctly adds request_async_id as field 4.


62-67: LGTM!

The DisconnectRequest correctly adds request_async_id as field 2.


70-101: LGTM!

Both PublishTrackRequest and UnpublishTrackRequest correctly add request_async_id as field 4.


104-152: LGTM!

The PublishDataRequest, PublishTranscriptionRequest, and PublishSipDtmfRequest messages correctly add request_async_id with appropriate field numbers.


155-192: LGTM!

The SetLocalMetadataRequest, SendChatMessageRequest, and EditChatMessageRequest messages correctly add request_async_id with appropriate field numbers.


195-226: LGTM!

The SetLocalAttributesRequest and SetLocalNameRequest messages correctly add request_async_id as field 3.


235-254: LGTM!

The GetSessionStatsRequest correctly adds request_async_id as field 2.


657-706: LGTM!

The SendStreamHeaderRequest, SendStreamChunkRequest, and SendStreamTrailerRequest messages all correctly add request_async_id as field 5.

livekit-ffi/protocol/rpc.proto (1)

27-34: LGTM!

The PerformRpcRequest correctly adds request_async_id as field 6, following the established pattern across other protocol files.

livekit-ffi/src/server/audio_source.rs (1)

70-113: LGTM!

The implementation correctly uses server.resolve_async_id(capture.request_async_id) to either use the client-provided ID or generate a new one. The resolved async_id is properly propagated to both the synchronous response and the async callback, ensuring clients can correlate their requests. This pattern is consistently applied across the entire codebase.

livekit-ffi/src/server/requests.rs (3)

67-77: LGTM!

The change correctly uses resolve_async_id to allow clients to provide their own async ID for request-response correlation. The ID is consistently used in both the synchronous response and the asynchronous callback.


406-432: LGTM!

Consistent application of resolve_async_id for the GetStats handler.


729-769: LGTM!

Consistent application of resolve_async_id for the GetSessionStats handler.

livekit-ffi/src/server/participant.rs (7)

56-86: LGTM!

The perform_rpc method correctly uses resolve_async_id to support client-provided correlation IDs. The pattern is well-applied with the ID used in both the response and callback.


145-158: LGTM!

Consistent application of resolve_async_id for send_file.


165-178: LGTM!

Consistent application of resolve_async_id for send_text.


185-198: LGTM!

Consistent application of resolve_async_id for send_bytes.


205-221: LGTM!

Consistent application of resolve_async_id for stream_bytes.


228-244: LGTM!

Consistent application of resolve_async_id for stream_text.


247-279: LGTM - Correctly retains next_id() for server-initiated invocation tracking.

The forward_rpc_method_invocation function correctly continues to use server.next_id() for invocation_id since this is a server-generated ID for internal RPC method invocation tracking, not a client-provided correlation ID.

livekit-ffi/src/server/data_stream.rs (7)

94-108: LGTM!

The read_all method correctly uses resolve_async_id for async correlation. The signature change to accept the request parameter is necessary to access request_async_id.


110-130: LGTM!

Consistent application of resolve_async_id for write_to_file.


174-188: LGTM!

Consistent application of resolve_async_id for TextStreamReader::read_all.


206-223: LGTM!

Consistent application of resolve_async_id for ByteStreamWriter::write.


225-244: LGTM!

Consistent application of resolve_async_id for ByteStreamWriter::close.


262-279: LGTM!

Consistent application of resolve_async_id for TextStreamWriter::write.


281-300: LGTM!

Consistent application of resolve_async_id for TextStreamWriter::close.

livekit-ffi/src/server/room.rs (14)

119-121: LGTM!

The connect method correctly uses resolve_async_id to allow clients to correlate connection requests with their callbacks.


338-365: LGTM!

The publish_data method correctly uses resolve_async_id. The cloning of topic and destination_identities before calling resolve_async_id is appropriate since these fields are needed for building the FfiDataPacket.


373-403: LGTM!

Consistent application of resolve_async_id for publish_transcription.


412-438: LGTM!

Consistent application of resolve_async_id for publish_sip_dtmf. The cloning pattern matches publish_data.


449-509: LGTM!

Consistent application of resolve_async_id for publish_track.


521-548: LGTM!

Consistent application of resolve_async_id for unpublish_track.


556-571: LGTM!

Consistent application of resolve_async_id for set_local_metadata.


579-590: LGTM!

Consistent application of resolve_async_id for set_local_name.


598-622: LGTM!

Consistent application of resolve_async_id for set_local_attributes.


630-668: LGTM!

Consistent application of resolve_async_id for send_chat_message.


676-715: LGTM!

Consistent application of resolve_async_id for edit_chat_message.


725-746: LGTM!

Consistent application of resolve_async_id for send_stream_header.


754-776: LGTM!

Consistent application of resolve_async_id for send_stream_chunk.


784-805: LGTM!

Consistent application of resolve_async_id for send_stream_trailer.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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

Copy link
Contributor

@cloudwebrtc cloudwebrtc left a comment

Choose a reason for hiding this comment

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

lgtm!

Copy link
Contributor

@ladvoc ladvoc left a comment

Choose a reason for hiding this comment

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

LGTM ✅, just a few unnecessary clones that should be removed prior to merging.

let topic = publish.topic;
let destination_identities = publish.destination_identities;
let async_id = server.next_id();
let topic = publish.topic.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Cloning topic and destination_identities is not necessary.

let digit = publish.digit;
let destination_identities = publish.destination_identities;
let async_id = server.next_id();
let digit = publish.digit.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Same here.

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.

4 participants