Skip to content

Commit

Permalink
fix: retryable location hint (#1505)
Browse files Browse the repository at this point in the history
Sometimes, it may take longer than 2000 ms. to retrieve the approximate location of the user.
We now try up to three times before we eventually give up.
  • Loading branch information
oliverlaz authored Oct 2, 2024
1 parent 7131bd2 commit 087417f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 22 deletions.
1 change: 1 addition & 0 deletions packages/client/src/coordinator/connection/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class StreamClient {
this.locationHint = getLocationHint(
options?.locationHintUrl,
options?.locationHintTimeout,
options?.locationHintMaxAttempts,
);
}

Expand Down
50 changes: 28 additions & 22 deletions packages/client/src/coordinator/connection/location.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
import { getLogger } from '../../logger';

const logger = getLogger(['location']);
const HINT_URL = `https://hint.stream-io-video.com/`;

export const getLocationHint = async (
hintUrl: string = HINT_URL,
timeout: number = 2000,
) => {
const abortController = new AbortController();
const timeoutId = setTimeout(() => abortController.abort(), timeout);
try {
const response = await fetch(hintUrl, {
method: 'HEAD',
signal: abortController.signal,
});
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
logger('debug', `Location header: ${awsPop}`);
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
} catch (e) {
logger('warn', `Failed to get location hint from ${hintUrl}`, e);
return 'ERR';
} finally {
clearTimeout(timeoutId);
}
hintUrl = `https://hint.stream-io-video.com/`,
timeout = 2000,
maxAttempts = 3,
): Promise<string> => {
const logger = getLogger(['location-hint']);

let attempt = 0;
let locationHint = 'ERR';
do {
const abortController = new AbortController();
const timeoutId = setTimeout(() => abortController.abort(), timeout);
try {
const response = await fetch(hintUrl, {
method: 'HEAD',
signal: abortController.signal,
});
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
logger('debug', `Location header: ${awsPop}`);
locationHint = awsPop.substring(0, 3); // AMS1-P2 -> AMS
} catch (e) {
logger('warn', `Failed to get location hint from ${hintUrl}`, e);
locationHint = 'ERR';
} finally {
clearTimeout(timeoutId);
}
} while (locationHint === 'ERR' && ++attempt < maxAttempts);

return locationHint;
};
4 changes: 4 additions & 0 deletions packages/client/src/coordinator/connection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export type StreamClientOptions = Partial<AxiosRequestConfig> & {
* The default timeout for requesting a location hint.
*/
locationHintTimeout?: number;
/**
* The maximum number of attempts to request a location hint.
*/
locationHintMaxAttempts?: number;
/**
* When true, user will be persisted on client. Otherwise if `connectUser` call fails, then you need to
* call `connectUser` again to retry.
Expand Down

0 comments on commit 087417f

Please sign in to comment.