Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions packages/livekit-rtc/src/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
//
// SPDX-License-Identifier: Apache-2.0
import { Mutex } from '@livekit/mutex';
import { EncryptionState, type EncryptionType } from '@livekit/rtc-ffi-bindings';
import type { FfiEvent } from '@livekit/rtc-ffi-bindings';
import {
EncryptionState,
type EncryptionType,
GetSessionStatsRequest,
} from '@livekit/rtc-ffi-bindings';
import type { FfiEvent, GetSessionStatsCallback } from '@livekit/rtc-ffi-bindings';
import { DisconnectReason, type OwnedParticipant } from '@livekit/rtc-ffi-bindings';
import type {
DataStream_Trailer,
Expand Down Expand Up @@ -191,6 +195,32 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
return this.sidPromise;
}

async getRtcStats() {
if (!this.isConnected || !this.ffiHandle) {
throw new Error('getRtcStats requires a connected room');
}
const res = FfiClient.instance.request<GetSessionStatsRequest>({
message: {
case: 'getSessionStats',
value: {
roomHandle: this.ffiHandle.handle,
},
},
});
const cb = await FfiClient.instance.waitFor<GetSessionStatsCallback>(
(ev: FfiEvent) =>
ev.message.case === 'getSessionStats' && ev.message.value.asyncId === res.requestAsyncId,
Comment on lines +202 to +212
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Wrong async ID field name causes getRtcStats to hang forever

The getRtcStats method accesses res.requestAsyncId to match the callback event, but every other async FFI method in the codebase (simulateScenario at room.ts:387, connect at room.ts:293, disconnect at room.ts:356, and all methods in participant.ts) uses res.asyncId. The response object returned by FfiClient.instance.request() will have an asyncId field (matching the FFI response protobuf), not requestAsyncId. At runtime, res.requestAsyncId evaluates to undefined, so the predicate in waitFor never matches any incoming event. This causes the method to hang indefinitely until the room disconnects and the AbortSignal fires, at which point it rejects with an abort error instead of returning stats.

Additionally, the type parameter is GetSessionStatsRequest instead of a Response type (every other call site uses the corresponding *Response type, e.g., SimulateScenarioResponse, ConnectResponse).

Prompt for agents
In packages/livekit-rtc/src/room.ts, the getRtcStats method has two issues on lines 202 and 212:

1. Line 202: The type parameter for FfiClient.instance.request should be the response type (likely GetSessionStatsResponse), not GetSessionStatsRequest. Every other call site in room.ts and participant.ts uses the *Response type (e.g. SimulateScenarioResponse, ConnectResponse, DisconnectResponse).

2. Line 212: res.requestAsyncId should be res.asyncId. Every other async Ffi method in the codebase uses res.asyncId to correlate the callback. Using requestAsyncId results in undefined at runtime, causing the waitFor predicate to never match.

You will need to check if GetSessionStatsResponse is exported from @livekit/rtc-ffi-bindings and import it, then change the type parameter on request<> and change requestAsyncId to asyncId.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

{ signal: this.disconnectController.signal },
);
if (cb.message.case === 'error') {
throw new Error(cb.message.value);
} else if (cb.message.case === 'result') {
return cb.message.value;
} else {
throw new Error('could not retrieve rtc stats');
}
}

get numParticipants(): number {
return this.info?.numParticipants ?? 0;
}
Expand Down
Loading