diff --git a/frontend/app/api/backend/[...path]/route.ts b/frontend/app/api/backend/[...path]/route.ts index f53ab8d..b2955ac 100644 --- a/frontend/app/api/backend/[...path]/route.ts +++ b/frontend/app/api/backend/[...path]/route.ts @@ -2,7 +2,8 @@ import { NextRequest, NextResponse } from "next/server"; export const dynamic = "force-dynamic"; -const UPSTREAM_TIMEOUT_MS = 18_000; +const DEFAULT_UPSTREAM_TIMEOUT_MS = 18_000; +const HEALTH_UPSTREAM_TIMEOUT_MS = 70_000; const ROUTE_METHODS: Array<{ pattern: RegExp; methods: Set }> = [ { pattern: /^health$/, methods: new Set(["GET"]) }, @@ -88,7 +89,13 @@ async function proxyRequest(request: NextRequest, context: RouteContext) { } const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), UPSTREAM_TIMEOUT_MS); + // A sleeping Render backend can need well over the ordinary request timeout + // before its health endpoint answers. Keep only this readiness probe alive + // long enough to wake it; normal application requests retain the tighter + // timeout after readiness has been established. + const upstreamTimeoutMs = + path === "health" ? HEALTH_UPSTREAM_TIMEOUT_MS : DEFAULT_UPSTREAM_TIMEOUT_MS; + const timeoutId = setTimeout(() => controller.abort(), upstreamTimeoutMs); try { const body = ["GET", "HEAD"].includes(request.method) diff --git a/frontend/components/FoodSearchPlaceholder.tsx b/frontend/components/FoodSearchPlaceholder.tsx index 0f30ca8..690784e 100644 --- a/frontend/components/FoodSearchPlaceholder.tsx +++ b/frontend/components/FoodSearchPlaceholder.tsx @@ -368,7 +368,7 @@ export function FoodSearchPlaceholder() { setError(null); setDidSearch(true); setSearchStatus( - "Connecting to the food service. The first search can take up to a minute while it starts." + "Connecting to the food service. After inactivity, startup can take up to 90 seconds." ); try { diff --git a/frontend/components/XamanLoginPanel.tsx b/frontend/components/XamanLoginPanel.tsx index 9bffb75..9a9a237 100644 --- a/frontend/components/XamanLoginPanel.tsx +++ b/frontend/components/XamanLoginPanel.tsx @@ -55,7 +55,7 @@ export function XamanLoginPanel() { setError(null); setIsLoading(true); setLoginStatus( - "Connecting securely. On the first visit, the service can take up to a minute to start." + "Connecting securely. After inactivity, startup can take up to 90 seconds." ); try { diff --git a/frontend/lib/backendRequest.ts b/frontend/lib/backendRequest.ts index 11d6cfe..bdedf69 100644 --- a/frontend/lib/backendRequest.ts +++ b/frontend/lib/backendRequest.ts @@ -1,7 +1,7 @@ export const DEFAULT_BACKEND_TIMEOUT_MS = 20_000; -export const DEFAULT_BACKEND_WARMUP_TIMEOUT_MS = 65_000; +export const DEFAULT_BACKEND_WARMUP_TIMEOUT_MS = 90_000; -const BACKEND_WARMUP_ATTEMPT_TIMEOUT_MS = 12_000; +const BACKEND_WARMUP_ATTEMPT_TIMEOUT_MS = 70_000; const BACKEND_WARMUP_RETRY_DELAY_MS = 2_000; export class BackendRequestTimeoutError extends Error {