From 3b9d01af9d34b053c2c2d814579f8937f7d270fe Mon Sep 17 00:00:00 2001 From: Linus Flood Date: Wed, 11 Jun 2025 12:39:58 +0000 Subject: [PATCH] Merged in feat/sw-3006-timeout-fetch (pull request #2335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(SW-3006): added default timeout to all requests * feat(sw-3006): added default timeout to all requests * Fixed spreading Approved-by: Joakim Jäderberg --- .../sas-x-scandic/callback/route.ts | 1 + apps/scandic-web/auth.ts | 1 + apps/scandic-web/lib/api/index.ts | 51 ++++++++++--------- apps/scandic-web/lib/graphql/request.ts | 7 ++- apps/scandic-web/middlewares/redirect.ts | 3 +- .../netlify/functions/sitemap-manual.mts | 1 + .../scandic-web/netlify/functions/sitemap.mts | 1 + .../netlify/functions/warmup-background.mts | 1 + apps/scandic-web/netlify/utils/hoteldata.ts | 1 + .../server/routers/hotels/query.ts | 4 +- .../server/routers/partners/jobylon/query.ts | 1 + .../partners/sas/otp/request/requestOtp.ts | 1 + .../partners/sas/otp/verify/verifyOtp.ts | 1 + apps/scandic-web/server/tokenManager.ts | 1 + 14 files changed, 46 insertions(+), 29 deletions(-) diff --git a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts index 11bc9f268..2122e8d8f 100644 --- a/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts +++ b/apps/scandic-web/app/[lang]/(partner)/(sas)/(protected)/sas-x-scandic/callback/route.ts @@ -55,6 +55,7 @@ export async function GET( ).toString(), client_id: env.SAS_AUTH_CLIENTID, }), + signal: AbortSignal.timeout(15_000), } ) diff --git a/apps/scandic-web/auth.ts b/apps/scandic-web/auth.ts index 67a5d5f6c..f62dc4a02 100644 --- a/apps/scandic-web/auth.ts +++ b/apps/scandic-web/auth.ts @@ -36,6 +36,7 @@ async function refreshTokens(token: JWT) { "Content-Type": "application/x-www-form-urlencoded", }, method: "POST", + signal: AbortSignal.timeout(15_000), }) const new_tokens = await response.json() diff --git a/apps/scandic-web/lib/api/index.ts b/apps/scandic-web/lib/api/index.ts index 532750f9e..568e4da60 100644 --- a/apps/scandic-web/lib/api/index.ts +++ b/apps/scandic-web/lib/api/index.ts @@ -21,7 +21,7 @@ const defaultOptions: RequestInit = { } const wrappedFetch = fetchRetry(fetch, { - retries: 3, + retries: 2, retryDelay: function (attempt) { return Math.pow(2, attempt) * 150 // 150, 300, 600 }, @@ -35,10 +35,11 @@ export async function get( const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() - return wrappedFetch( - url, - merge.all([defaultOptions, { method: "GET" }, options]) - ) + + return wrappedFetch(url, { + ...merge.all([defaultOptions, { method: "GET" }, options]), + signal: AbortSignal.timeout(15_000), + }) } export async function patch( @@ -50,14 +51,14 @@ export async function patch( const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() - return wrappedFetch( - url, - merge.all([ + return wrappedFetch(url, { + ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "PATCH" }, requestOptions, - ]) - ) + ]), + signal: AbortSignal.timeout(15_000), + }) } export async function post( @@ -69,14 +70,14 @@ export async function post( const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() - return wrappedFetch( - url, - merge.all([ + return wrappedFetch(url, { + ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "POST" }, requestOptions, - ]) - ) + ]), + signal: AbortSignal.timeout(15_000), + }) } export async function put( @@ -88,14 +89,14 @@ export async function put( const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() - return wrappedFetch( - url, - merge.all([ + return wrappedFetch(url, { + ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "PUT" }, requestOptions, - ]) - ) + ]), + signal: AbortSignal.timeout(15_000), + }) } export async function remove( @@ -107,12 +108,12 @@ export async function remove( const url = new URL(env.API_BASEURL) url.pathname = endpoint url.search = new URLSearchParams(params).toString() - return wrappedFetch( - url, - merge.all([ + return wrappedFetch(url, { + ...merge.all([ defaultOptions, { body: JSON.stringify(body), method: "DELETE" }, requestOptions, - ]) - ) + ]), + signal: AbortSignal.timeout(15_000), + }) } diff --git a/apps/scandic-web/lib/graphql/request.ts b/apps/scandic-web/lib/graphql/request.ts index db2bf5800..fc00bf565 100644 --- a/apps/scandic-web/lib/graphql/request.ts +++ b/apps/scandic-web/lib/graphql/request.ts @@ -73,12 +73,15 @@ function internalRequest( params?: RequestInit ) { const wrappedFetch = fetchRetry(fetch, { - retries: 3, + retries: 2, retryDelay: function (attempt) { return Math.pow(2, attempt) * 150 // 150, 300, 600 }, }) - return wrappedFetch(url, params) + return wrappedFetch(url, { + ...params, + signal: AbortSignal.timeout(15_000), + }) }), }) diff --git a/apps/scandic-web/middlewares/redirect.ts b/apps/scandic-web/middlewares/redirect.ts index 7b99d7a50..0ce81d954 100644 --- a/apps/scandic-web/middlewares/redirect.ts +++ b/apps/scandic-web/middlewares/redirect.ts @@ -26,6 +26,7 @@ async function fetchAndCacheRedirect(lang: Lang, pathname: string) { headers: { "Content-Type": "application/json", }, + signal: AbortSignal.timeout(15_000), } ) @@ -39,7 +40,7 @@ async function fetchAndCacheRedirect(lang: Lang, pathname: string) { return null }, // longer once tested - "1m" + "1d" ) } diff --git a/apps/scandic-web/netlify/functions/sitemap-manual.mts b/apps/scandic-web/netlify/functions/sitemap-manual.mts index a6f1ac88f..e8fec1e7c 100644 --- a/apps/scandic-web/netlify/functions/sitemap-manual.mts +++ b/apps/scandic-web/netlify/functions/sitemap-manual.mts @@ -15,6 +15,7 @@ export default async (request: Request, _context: Context) => { ) const response = await fetch(url, { headers, + signal: AbortSignal.timeout(30_000), }) if (!response.ok) { const text = await response.text() diff --git a/apps/scandic-web/netlify/functions/sitemap.mts b/apps/scandic-web/netlify/functions/sitemap.mts index 4dafdfb7e..c5a74cacc 100644 --- a/apps/scandic-web/netlify/functions/sitemap.mts +++ b/apps/scandic-web/netlify/functions/sitemap.mts @@ -18,6 +18,7 @@ export default async (request: Request, _context: Context) => { ) const response = await fetch(url, { headers, + signal: AbortSignal.timeout(30_000), }) if (!response.ok) { const text = await response.text() diff --git a/apps/scandic-web/netlify/functions/warmup-background.mts b/apps/scandic-web/netlify/functions/warmup-background.mts index ecdbf67d1..4f52a5061 100644 --- a/apps/scandic-web/netlify/functions/warmup-background.mts +++ b/apps/scandic-web/netlify/functions/warmup-background.mts @@ -122,6 +122,7 @@ async function callWarmup(key: WarmupFunctionsKey, context: Context) { cache: "no-store", Authorization: `Bearer ${warmupToken}`, }, + signal: AbortSignal.timeout(30_000), }) if (!response.ok) { diff --git a/apps/scandic-web/netlify/utils/hoteldata.ts b/apps/scandic-web/netlify/utils/hoteldata.ts index 95a5c924d..fe6aac35c 100644 --- a/apps/scandic-web/netlify/utils/hoteldata.ts +++ b/apps/scandic-web/netlify/utils/hoteldata.ts @@ -11,6 +11,7 @@ export async function warmupHotelDataOnLang(lang: Lang) { `${PUBLIC_URL}/api/hoteldata?lang=${lang}`, { headers: { cache: "no-store" }, + signal: AbortSignal.timeout(30_000), } ) diff --git a/apps/scandic-web/server/routers/hotels/query.ts b/apps/scandic-web/server/routers/hotels/query.ts index d28f0df07..f95775a69 100644 --- a/apps/scandic-web/server/routers/hotels/query.ts +++ b/apps/scandic-web/server/routers/hotels/query.ts @@ -880,7 +880,9 @@ export const hotelQueryRouter = router({ `coordinates:${address}`, async function () { const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${apiKey}` - const response = await fetch(url) + const response = await fetch(url, { + signal: AbortSignal.timeout(15_000), + }) const data = await response.json() if (data.status !== "OK") { diff --git a/apps/scandic-web/server/routers/partners/jobylon/query.ts b/apps/scandic-web/server/routers/partners/jobylon/query.ts index 3e7670d10..464b253c6 100644 --- a/apps/scandic-web/server/routers/partners/jobylon/query.ts +++ b/apps/scandic-web/server/routers/partners/jobylon/query.ts @@ -32,6 +32,7 @@ export const jobylonQueryRouter = router({ async () => { const response = await fetch(url, { cache: "no-cache", + signal: AbortSignal.timeout(15_000), }) if (!response.ok) { diff --git a/apps/scandic-web/server/routers/partners/sas/otp/request/requestOtp.ts b/apps/scandic-web/server/routers/partners/sas/otp/request/requestOtp.ts index 54fce9dc2..6bddbadc4 100644 --- a/apps/scandic-web/server/routers/partners/sas/otp/request/requestOtp.ts +++ b/apps/scandic-web/server/routers/partners/sas/otp/request/requestOtp.ts @@ -110,6 +110,7 @@ async function fetchRequestOtp({ sasAuthToken }: { sasAuthToken: string }) { body: JSON.stringify({ referenceId: uuidv4(), }), + signal: AbortSignal.timeout(15_000), }) } diff --git a/apps/scandic-web/server/routers/partners/sas/otp/verify/verifyOtp.ts b/apps/scandic-web/server/routers/partners/sas/otp/verify/verifyOtp.ts index 9539479ba..2d33073b8 100644 --- a/apps/scandic-web/server/routers/partners/sas/otp/verify/verifyOtp.ts +++ b/apps/scandic-web/server/routers/partners/sas/otp/verify/verifyOtp.ts @@ -87,6 +87,7 @@ async function fetchVerifyOtp(input: z.infer) { otpCode: input.otp, databaseUUID: databaseUUID, }), + signal: AbortSignal.timeout(15_000), } ) } diff --git a/apps/scandic-web/server/tokenManager.ts b/apps/scandic-web/server/tokenManager.ts index cb2e6fa30..56bf00947 100644 --- a/apps/scandic-web/server/tokenManager.ts +++ b/apps/scandic-web/server/tokenManager.ts @@ -91,6 +91,7 @@ async function fetchServiceToken(scopes: string[]) { client_secret: env.CURITY_CLIENT_SECRET_SERVICE, scope: scopes.join(" "), }), + signal: AbortSignal.timeout(15_000), }) if (!response.ok) {