Skip to content

Commit 2604cf6

Browse files
authored
feat: improve redirect URL caching for WebRTC offers (#612)
1 parent 013f5c8 commit 2604cf6

File tree

1 file changed

+62
-24
lines changed

1 file changed

+62
-24
lines changed

packages/core-web/src/webrtc/shared.ts

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,32 @@ export async function constructClientOffer(
194194
const playbackIdPattern = /([/+])([^/+?]+)$/;
195195
const REPLACE_PLACEHOLDER = "PLAYBACK_ID";
196196

197-
let cachedRedirectUrl: URL | null = null;
197+
const MAX_REDIRECT_CACHE_SIZE = 10;
198+
const redirectUrlCache = new Map<string, URL>();
199+
200+
function getCachedTemplate(key: string): URL | undefined {
201+
const cachedItem = redirectUrlCache.get(key);
202+
203+
if (cachedItem) {
204+
redirectUrlCache.delete(key);
205+
redirectUrlCache.set(key, cachedItem);
206+
}
207+
208+
return cachedItem;
209+
}
210+
211+
function setCachedTemplate(key: string, value: URL): void {
212+
if (redirectUrlCache.has(key)) {
213+
redirectUrlCache.delete(key);
214+
} else if (redirectUrlCache.size >= MAX_REDIRECT_CACHE_SIZE) {
215+
const oldestKey = redirectUrlCache.keys().next().value;
216+
if (oldestKey) {
217+
redirectUrlCache.delete(oldestKey);
218+
}
219+
}
220+
221+
redirectUrlCache.set(key, value);
222+
}
198223

199224
async function postSDPOffer(
200225
endpoint: string,
@@ -208,23 +233,24 @@ async function postSDPOffer(
208233
sdpTimeout ?? DEFAULT_TIMEOUT,
209234
);
210235

211-
const url = new URL(endpoint);
236+
const urlForPost = new URL(endpoint);
237+
const parsedMatches = urlForPost.pathname.match(playbackIdPattern);
238+
const currentPlaybackId = parsedMatches?.[2];
212239

213-
const parsedMatches = url.pathname.match(playbackIdPattern);
240+
const cachedTemplateUrl = getCachedTemplate(endpoint);
214241

215242
// if we both have a cached redirect URL and a match for the playback ID,
216243
// use these to shortcut the typical webrtc redirect flow
217-
if (cachedRedirectUrl && parsedMatches?.[2]) {
218-
const clonedCachedUrl = new URL(cachedRedirectUrl);
219-
220-
url.host = clonedCachedUrl.host;
221-
url.pathname = clonedCachedUrl.pathname.replace(
244+
if (cachedTemplateUrl && currentPlaybackId) {
245+
urlForPost.host = cachedTemplateUrl.host;
246+
urlForPost.pathname = cachedTemplateUrl.pathname.replace(
222247
REPLACE_PLACEHOLDER,
223-
parsedMatches[2],
248+
currentPlaybackId,
224249
);
250+
urlForPost.search = cachedTemplateUrl.search;
225251
}
226252

227-
const response = await fetch(url.toString(), {
253+
const response = await fetch(urlForPost.toString(), {
228254
method: "POST",
229255
mode: "cors",
230256
headers: {
@@ -255,12 +281,21 @@ export async function getRedirectUrl(
255281
timeout: number | null,
256282
) {
257283
try {
258-
if (cachedRedirectUrl) {
259-
const inputUrl = new URL(endpoint);
260-
261-
inputUrl.host = cachedRedirectUrl.host;
262-
263-
return inputUrl;
284+
const cachedTemplateUrl = getCachedTemplate(endpoint);
285+
286+
if (cachedTemplateUrl) {
287+
const currentIngestUrl = new URL(endpoint);
288+
const matches = currentIngestUrl.pathname.match(playbackIdPattern);
289+
const currentPlaybackId = matches?.[2];
290+
291+
if (currentPlaybackId) {
292+
const finalRedirectUrl = new URL(cachedTemplateUrl);
293+
finalRedirectUrl.pathname = cachedTemplateUrl.pathname.replace(
294+
REPLACE_PLACEHOLDER,
295+
currentPlaybackId,
296+
);
297+
return finalRedirectUrl;
298+
}
264299
}
265300

266301
const id = setTimeout(
@@ -278,20 +313,23 @@ export async function getRedirectUrl(
278313

279314
clearTimeout(id);
280315

281-
const parsedUrl = new URL(response.url);
316+
const actualRedirectedUrl = new URL(response.url);
282317

283-
if (parsedUrl) {
284-
const cachedUrl = new URL(parsedUrl);
285-
cachedUrl.pathname = cachedUrl.pathname.replace(
318+
if (actualRedirectedUrl) {
319+
const templateForCache = new URL(actualRedirectedUrl);
320+
templateForCache.pathname = templateForCache.pathname.replace(
286321
playbackIdPattern,
287322
`$1${REPLACE_PLACEHOLDER}`,
288323
);
289-
if (!cachedUrl.searchParams.has("ingestpb", "true")) {
290-
cachedRedirectUrl = cachedUrl;
324+
325+
if (
326+
!templateForCache.searchParams.has("ingestpb") ||
327+
templateForCache.searchParams.get("ingestpb") !== "true"
328+
) {
329+
setCachedTemplate(endpoint, templateForCache);
291330
}
292331
}
293-
294-
return parsedUrl;
332+
return actualRedirectedUrl;
295333
} catch (e) {
296334
return null;
297335
}

0 commit comments

Comments
 (0)