add retries and be more specific when we fall back to legacy endpoint

This commit is contained in:
Timo K
2026-01-07 17:21:08 +01:00
parent 0eeed4e18e
commit 5556d363b9

View File

@@ -5,7 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details. Please see LICENSE in the repository root for full details.
*/ */
import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk"; import {
HTTPError,
retryNetworkOperation,
type IOpenIDToken,
type MatrixClient,
} from "matrix-js-sdk";
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
import { type Logger } from "matrix-js-sdk/lib/logger"; import { type Logger } from "matrix-js-sdk/lib/logger";
@@ -111,33 +116,49 @@ export async function getSFUConfigWithOpenID(
// since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) // since we are not sending the new matrix2.0 sticky events (no hashed identity in the event)
if (forceOldJwtEndpoint === false) { if (forceOldJwtEndpoint === false) {
try { try {
sfuConfig = await getLiveKitJWTWithDelayDelegation( await retryNetworkOperation(4, async () => {
membership, sfuConfig = await getLiveKitJWTWithDelayDelegation(
serviceUrl, membership,
roomId, serviceUrl,
openIdToken, roomId,
delayEndpointBaseUrl, openIdToken,
delayId, delayEndpointBaseUrl,
); delayId,
logger?.info(`Got JWT from call's active focus URL.`); );
logger?.info(`Got JWT from call's active focus URL.`);
});
} catch (e) { } catch (e) {
sfuConfig = undefined; if (e instanceof NotSupportedError) {
logger?.warn( logger?.warn(
`Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy) Not supported`,
e, e,
); );
logger?.info(`Got JWT from call's active focus URL.`); sfuConfig = undefined;
} else {
logger?.warn(
`Failed fetching jwt with matrix 2.0 endpoint other issues -> not going to try with legacy endpoint`,
e,
);
}
} }
} }
// DEPRECATED
// Either forceOldJwtEndpoint = true or getLiveKitJWTWithDelayDelegation throws -> reset sfuConfig = undefined // Either forceOldJwtEndpoint = true or getLiveKitJWTWithDelayDelegation throws -> reset sfuConfig = undefined
if (sfuConfig === undefined) { if (sfuConfig === undefined) {
sfuConfig = await getLiveKitJWT( await retryNetworkOperation(4, async () => {
membership.deviceId, sfuConfig = await getLiveKitJWT(
serviceUrl, membership.deviceId,
roomId, serviceUrl,
openIdToken, roomId,
); openIdToken,
);
});
logger?.info(`Got JWT from call's active focus URL.`);
}
if (!sfuConfig) {
throw new Error("No `sfuConfig` after trying with old and new endpoints");
} }
// Pull the details from the JWT // Pull the details from the JWT
@@ -161,25 +182,28 @@ async function getLiveKitJWT(
matrixRoomId: string, matrixRoomId: string,
openIDToken: IOpenIDToken, openIDToken: IOpenIDToken,
): Promise<{ url: string; jwt: string }> { ): Promise<{ url: string; jwt: string }> {
try { const res = await fetch(livekitServiceURL + "/sfu/get", {
const res = await fetch(livekitServiceURL + "/sfu/get", { method: "POST",
method: "POST", headers: {
headers: { "Content-Type": "application/json",
"Content-Type": "application/json", },
}, body: JSON.stringify({
body: JSON.stringify({ // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used.
// This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. room: matrixRoomId,
room: matrixRoomId, openid_token: openIDToken,
openid_token: openIDToken, device_id: deviceId,
device_id: deviceId, }),
}), });
}); if (!res.ok) {
if (!res.ok) { throw new Error("SFU Config fetch failed with status code " + res.status);
throw new Error("SFU Config fetch failed with status code " + res.status); }
} return await res.json();
return await res.json(); }
} catch (e) {
throw new Error("SFU Config fetch failed with exception", { cause: e }); class NotSupportedError extends Error {
public constructor(message: string) {
super(message);
this.name = "NotSupported";
} }
} }
@@ -216,19 +240,20 @@ export async function getLiveKitJWTWithDelayDelegation(
}; };
} }
try { const res = await fetch(livekitServiceURL + "/get_token", {
const res = await fetch(livekitServiceURL + "/get_token", { method: "POST",
method: "POST", headers: {
headers: { "Content-Type": "application/json",
"Content-Type": "application/json", },
}, body: JSON.stringify({ ...body, ...bodyDalayParts }),
body: JSON.stringify({ ...body, ...bodyDalayParts }), });
}); if (!res.ok) {
if (!res.ok) { const msg = "SFU Config fetch failed with status code " + res.status;
throw new Error("SFU Config fetch failed with status code " + res.status); if (res.status === 404) {
throw new NotSupportedError(msg);
} else {
throw new Error(msg);
} }
return await res.json();
} catch (e) {
throw new Error("SFU Config fetch failed with exception " + e);
} }
return await res.json();
} }