@@ -194,7 +194,32 @@ export async function constructClientOffer(
194194const playbackIdPattern = / ( [ / + ] ) ( [ ^ / + ? ] + ) $ / ;
195195const 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
199224async 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