Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .changes/rpc-max-round-trip-latency
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
patch type="added" "Allow customizing `maxRoundTripLatency` on `LocalParticipant.performRpc` for high-latency networks
12 changes: 10 additions & 2 deletions Sources/LiveKit/Core/RpcClientManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ import Foundation
/// publishing of v1 RPC packets / v2 RPC request streams. `LocalParticipant.performRpc`
/// is a one-line proxy that forwards into this actor.
actor RpcClientManager: Loggable {
/// Default upper bound on round-trip latency to the destination, in seconds. Used by the
/// ack watchdog and to clamp the effective response timeout. Exposed so the public
/// `LocalParticipant.performRpc` overloads can share the same default.
static let defaultMaxRoundTripLatency: TimeInterval = 7

/// Default timeout for receiving a response after the initial connection, in seconds.
static let defaultResponseTimeout: TimeInterval = 15

private weak var room: Room?

private var pendingAcks: Set<String> = Set()
Expand Down Expand Up @@ -50,15 +58,15 @@ actor RpcClientManager: Loggable {
func performRpc(destinationIdentity: Participant.Identity,
method: String,
payload: String,
responseTimeout: TimeInterval = 15) async throws -> String
responseTimeout: TimeInterval = RpcClientManager.defaultResponseTimeout,
maxRoundTripLatency: TimeInterval = RpcClientManager.defaultMaxRoundTripLatency) async throws -> String
{
let room = try requireRoom()

let remoteClientProtocol = room.remoteParticipants[destinationIdentity]?.clientProtocol ?? .v0
let useStreamTransport = remoteClientProtocol >= .v1 && Self.serverSupportsRpcV2(room.serverVersion)

let requestId = UUID().uuidString
let maxRoundTripLatency: TimeInterval = 7
let minEffectiveTimeout: TimeInterval = maxRoundTripLatency + 1
let effectiveTimeout = max(responseTimeout, minEffectiveTimeout)

Expand Down
16 changes: 11 additions & 5 deletions Sources/LiveKit/Participant/LocalParticipant+RPC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,33 @@ public extension LocalParticipant {
/// 15 KB payload size limit (otherwise rejected with `REQUEST_PAYLOAD_TOO_LARGE`).
///
/// ObjC: auto-generated as
/// `performRpcWithDestinationIdentity:method:payload:responseTimeout:completionHandler:`.
/// `performRpcWithDestinationIdentity:method:payload:responseTimeout:maxRoundTripLatency:completionHandler:`.
///
/// - Parameters:
/// - destinationIdentity: The identity of the destination participant
/// - method: The method name to call
/// - payload: The payload to pass to the method
/// - responseTimeout: Timeout for receiving a response after the initial connection (in seconds).
/// If a value less than 8s is provided, it will be automatically clamped to 8s
/// to ensure sufficient time for round-trip latency buffering.
/// If a value less than `maxRoundTripLatency + 1` is provided, it will be automatically
/// clamped to that floor to ensure sufficient time for round-trip latency buffering.
/// Default: 15s.
/// - maxRoundTripLatency: Upper bound on round-trip latency to the destination, in seconds.
/// If no ack arrives within this window the call is rejected with
/// `RpcError.BuiltInError.connectionTimeout`. Increase this on high-latency links where
/// the default is too tight. Default: 7s.
/// - Returns: The response payload
/// - Throws: RpcError on failure. Details in RpcError.message
func performRpc(destinationIdentity: Identity,
method: String,
payload: String,
responseTimeout: TimeInterval = 15) async throws -> String
responseTimeout: TimeInterval = 15,
maxRoundTripLatency: TimeInterval = 7) async throws -> String
{
try await requireRoom().rpcClient.performRpc(destinationIdentity: destinationIdentity,
method: method,
payload: payload,
responseTimeout: responseTimeout)
responseTimeout: responseTimeout,
maxRoundTripLatency: maxRoundTripLatency)
}
Comment thread
1egoman marked this conversation as resolved.

@available(*, deprecated, message: "registerRpcMethod(_:handler:) has been moved to room.")
Expand Down
1 change: 1 addition & 0 deletions Tests/LiveKitObjCTests/RpcObjCTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ - (void)testRegisterAndCallRpc {
method:@"greet"
payload:@"World"
responseTimeout:15.0
maxRoundTripLatency:7.0
completionHandler:^(NSString *response, NSError *err) {
XCTAssertNil(err);
rpcResponse = response;
Expand Down
Loading