diff --git a/src/lib/beds24.ts b/src/lib/beds24.ts index fa04e7a..3162b6d 100644 --- a/src/lib/beds24.ts +++ b/src/lib/beds24.ts @@ -64,6 +64,7 @@ function getRefreshToken(houseId: string): string | undefined { } const accessTokenCache = new Map(); +const pendingTokenRequests = new Map>(); async function getAccessToken(houseId: string): Promise { const refreshToken = getRefreshToken(houseId); @@ -78,26 +79,40 @@ async function getAccessToken(houseId: string): Promise { return cached.token; } - const response = await fetch(`${BEDS24_API_BASE}/authentication/token`, { - method: "GET", - headers: { refreshToken }, - }); - - if (!response.ok) { - throw new Error( - `Beds24 authentication error for house ${houseId}: ${response.status} ${response.statusText}` - ); + const inFlight = pendingTokenRequests.get(houseId); + if (inFlight) { + return inFlight; } - const data: { token: string; expiresIn: number } = await response.json(); + const tokenPromise = (async () => { + try { + const response = await fetch(`${BEDS24_API_BASE}/authentication/token`, { + method: "GET", + headers: { refreshToken }, + }); - // Refresh a minute early to avoid using a token that expires mid-request. - accessTokenCache.set(houseId, { - token: data.token, - expiresAt: Date.now() + Math.max(data.expiresIn - 60, 30) * 1000, - }); + if (!response.ok) { + throw new Error( + `Beds24 authentication error for house ${houseId}: ${response.status} ${response.statusText}` + ); + } - return data.token; + const data: { token: string; expiresIn: number } = await response.json(); + + // Refresh a minute early to avoid using a token that expires mid-request. + accessTokenCache.set(houseId, { + token: data.token, + expiresAt: Date.now() + Math.max(data.expiresIn - 60, 30) * 1000, + }); + + return data.token; + } finally { + pendingTokenRequests.delete(houseId); + } + })(); + + pendingTokenRequests.set(houseId, tokenPromise); + return tokenPromise; } async function beds24Get(