From fce7b6d4569165d483d48c2e7896034d099c1ff6 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 5 Aug 2025 17:44:22 +0200 Subject: [PATCH] refactor: move warmup to makePreferredLivekitFoci --- src/rtcSessionHelpers.ts | 133 ++++++++++----------------------------- 1 file changed, 34 insertions(+), 99 deletions(-) diff --git a/src/rtcSessionHelpers.ts b/src/rtcSessionHelpers.ts index 75c1ff60..33150b48 100644 --- a/src/rtcSessionHelpers.ts +++ b/src/rtcSessionHelpers.ts @@ -47,18 +47,47 @@ async function makePreferredLivekitFoci( preferredFoci.push(focusInUse); } + // Stop-gap solution for pre-warming the SFU. + // This is needed to ensure that the livekit room is created before we try to join the rtc session. + // This is because the livekit room creation is done by the auth service and this can be restricted to + // only specific users, so we need to ensure that the room is created before we try to send state events. + let shouldWarmup = true; + // Prioritize the .well-known/matrix/client, if available, over the configured SFU const domain = rtcSession.room.client.getDomain(); if (domain) { // we use AutoDiscovery instead of relying on the MatrixClient having already // been fully configured and started - const wellKnownFoci = await getFocusListFromWellKnown(domain, livekitAlias); - logger.log("Adding livekit focus from well known: ", wellKnownFoci); - preferredFoci.push(...wellKnownFoci); + const wellKnownFoci = (await AutoDiscovery.getRawClientConfig(domain))?.[ + FOCI_WK_KEY + ]; + if (Array.isArray(wellKnownFoci)) { + const validWellKnownFoci = wellKnownFoci + .filter((f) => !!f) + .filter(isLivekitFocusConfig) + .map((wellKnownFocus) => { + logger.log("Adding livekit focus from well known: ", wellKnownFocus); + return { ...wellKnownFocus, livekit_alias: livekitAlias }; + }); + if (validWellKnownFoci.length > 0) { + const toWarmup = validWellKnownFoci[0]; + await getSFUConfigWithOpenID(rtcSession.room.client, toWarmup); + shouldWarmup = false; + } + preferredFoci.push(...validWellKnownFoci); + } } - const focusFormConf = getFocusListFromConfig(livekitAlias); - if (focusFormConf) { + const urlFromConf = Config.get().livekit?.livekit_service_url; + if (urlFromConf) { + const focusFormConf: LivekitFocus = { + type: "livekit", + livekit_service_url: urlFromConf, + livekit_alias: livekitAlias, + }; + if (shouldWarmup) { + await getSFUConfigWithOpenID(rtcSession.room.client, focusFormConf); + } logger.log("Adding livekit focus from config: ", focusFormConf); preferredFoci.push(focusFormConf); } @@ -76,96 +105,6 @@ async function makePreferredLivekitFoci( // if (focusOtherMembers) preferredFoci.push(focusOtherMembers); } -async function getFocusListFromWellKnown( - domain: string, - alias: string, -): Promise { - if (domain) { - // we use AutoDiscovery instead of relying on the MatrixClient having already - // been fully configured and started - const wellKnownFoci = (await AutoDiscovery.getRawClientConfig(domain))?.[ - FOCI_WK_KEY - ]; - if (Array.isArray(wellKnownFoci)) { - return wellKnownFoci - .filter((f) => !!f) - .filter(isLivekitFocusConfig) - .map((wellKnownFocus) => { - return { ...wellKnownFocus, livekit_alias: alias }; - }); - } - } - return []; -} - -function getFocusListFromConfig(livekitAlias: string): LivekitFocus | null { - const urlFromConf = Config.get().livekit?.livekit_service_url; - if (urlFromConf) { - return { - type: "livekit", - livekit_service_url: urlFromConf, - livekit_alias: livekitAlias, - }; - } - return null; -} - -export async function getMyPreferredLivekitFoci( - domain: string | null, - livekitAlias: string, -): Promise { - if (domain) { - // we use AutoDiscovery instead of relying on the MatrixClient having already - // been fully configured and started - const wellKnownFociList = await getFocusListFromWellKnown( - domain, - livekitAlias, - ); - if (wellKnownFociList.length > 0) { - return wellKnownFociList[0]; - } - } - - const urlFromConf = Config.get().livekit?.livekit_service_url; - if (urlFromConf) { - return { - type: "livekit", - livekit_service_url: urlFromConf, - livekit_alias: livekitAlias, - }; - } - throw new MatrixRTCFocusMissingError(domain ?? ""); -} - -// Stop-gap solution for pre-warming the SFU. -// This is needed to ensure that the livekit room is created before we try to join the rtc session. -// This is because the livekit room creation is done by the auth service and this can be restricted to -// only specific users, so we need to ensure that the room is created before we try to join it. -async function preWarmSFU( - rtcSession: MatrixRTCSession, - livekitAlias: string, -): Promise { - const client = rtcSession.room.client; - // We need to make sure that the livekit room is created before sending the membership event - // because other joiners might not be able to join the call if the room does not exist yet. - const fociToWarmup = await getMyPreferredLivekitFoci( - client.getDomain(), - livekitAlias, - ); - - // Request a token in advance to warm up the livekit room. - // Let it throw if it fails, errors will be handled by the ErrorBoundary, if it fails now - // it will fail later when we try to join the room. - await getSFUConfigWithOpenID(client, fociToWarmup); - // For now we don't do anything with the token returned by `getSFUConfigWithOpenID`, it is just to ensure that we - // call the `sfu/get` endpoint so that the auth service create the room in advance if it can. - // Note: This is not actually checking that the room was created! If the roon creation is - // not done by the auth service, the call will fail later when we try to join the room; that case - // is a miss-configuration of the auth service, you should be able to create room in your selected SFU. - // A solution could be to call the internal `/validate` endpoint to check that the room exists, but this needs - // to access livekit internal APIs, so we don't do it for now. -} - export async function enterRTCSession( rtcSession: MatrixRTCSession, encryptMedia: boolean, @@ -184,10 +123,6 @@ export async function enterRTCSession( const { features, matrix_rtc_session: matrixRtcSessionConfig } = Config.get(); const useDeviceSessionMemberEvents = features?.feature_use_device_session_member_events; - - // Pre-warm the SFU to ensure that the room is created before anyone tries to join it. - await preWarmSFU(rtcSession, livekitAlias); - rtcSession.joinRoomSession( await makePreferredLivekitFoci(rtcSession, livekitAlias), makeActiveFocus(),