diff --git a/frontend/islands/GithubUserLink.tsx b/frontend/islands/GithubUserLink.tsx index 250238fb..da407582 100644 --- a/frontend/islands/GithubUserLink.tsx +++ b/frontend/islands/GithubUserLink.tsx @@ -6,6 +6,7 @@ import { cachedGitHubLogin } from "../utils/github.ts"; export function GitHubUserLink({ user }: { user?: User }) { const login = useSignal(""); + const error = useSignal(false); useEffect(() => { if (user) { @@ -13,10 +14,20 @@ export function GitHubUserLink({ user }: { user?: User }) { .then((login_) => { login.value = login_; }) - .catch(console.error); + .catch((error_) => { + console.error(error_); + + error.value = true; + }); } }); + if (error.value) { + return ( + Could not load GitHub username + ); + } + return login.value == "" ? loading... : GitHub; diff --git a/frontend/utils/github.ts b/frontend/utils/github.ts index 3ea14d65..f48e223d 100644 --- a/frontend/utils/github.ts +++ b/frontend/utils/github.ts @@ -5,15 +5,41 @@ import { getOrInsertItem } from "./client_cache.ts"; export async function cachedGitHubLogin(user: User): Promise { return await getOrInsertItem( `gh-login-${user.githubId}`, - () => - fetch(`https://api.github.com/user/${user.githubId}`, { - headers: { - "Content-Type": "application/json", - }, - }) - .then((r) => r.json()) - .then((data) => { - return data.login; - }), + () => { + const MAX_RETRIES = 3; + const fetchGithubUser = async (retryCount = 0) => { + const response = await fetch( + `https://api.github.com/user/${user.githubId}`, + { + headers: { + "Content-Type": "application/json", + }, + }, + ); + + if ( + response.status === 403 && + response.headers.get("x-ratelimit-remaining") === "0" + ) { + throw new Error("Github API rate limit exceeded"); + } + + const data = await response.json(); + + if (!data.login) { + if (retryCount >= MAX_RETRIES) { + throw new Error( + "Failed to fetch GitHub login after maximum retries", + ); + } + + await new Promise((resolve) => setTimeout(resolve, 100)); + return fetchGithubUser(retryCount + 1); + } + return data.login; + }; + + return fetchGithubUser(); + }, ); }