From fdd53b0dd94bfcf5cfd5226642a8dccde96250ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Mon, 24 Aug 2026 17:55:07 +0000 Subject: [PATCH] one switch for sidecar timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SIDECAR_TIMEOUTS=1 puts the old behaviour back — Bun's built-in fetch ceiling outbound, and the inbound drop at whatever each plugin declared. unset, which is the default, means no ceiling on either leg. one constant in one file rather than a knob per plugin: turning it on or off should not mean remembering which of eight routers to edit. Co-Authored-By: Claude Opus 5 Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043 --- .env.example | 5 +++++ src/servers/sidecar/create-proxy.ts | 28 +++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 461e82a2..74edbec2 100644 --- a/.env.example +++ b/.env.example @@ -85,3 +85,8 @@ PUBLIC_URL=http://localhost:9000 # Immich (officer-photos) is configured from the app, not from here — Photos → Connection. Instances and # their API keys live encrypted in `photos_config`, so the platform never sees a key. + +# Put request timeouts back on sidecar proxies. Unset is the default and means NO timeout on either leg: +# long requests arrive from everywhere (transcribing a 42-minute recording, a from-scratch music reindex) +# and every ceiling is a number somebody guessed. Set to 1 only to restore the old behaviour. +# SIDECAR_TIMEOUTS=1 diff --git a/src/servers/sidecar/create-proxy.ts b/src/servers/sidecar/create-proxy.ts index 3f88a525..677a2ad2 100644 --- a/src/servers/sidecar/create-proxy.ts +++ b/src/servers/sidecar/create-proxy.ts @@ -94,6 +94,19 @@ export type SidecarProxy = { getWsUrl: () => string | null; }; +/** + * The one switch for sidecar request timeouts. + * + * Off by default: no ceiling on either leg, because long requests arrive from everywhere and every + * ceiling is a number somebody guessed. Set `SIDECAR_TIMEOUTS=1` in `.env` and restart to put the old + * behaviour back — Bun's built-in fetch ceiling outbound, and the inbound drop at whatever each plugin + * declared (or the server's 60s default if it declared nothing). + * + * Here rather than per plugin so turning it on or off is one line in one file, and so nobody has to + * remember which of eight routers to edit. + */ +const TIMEOUTS_ON = process.env.SIDECAR_TIMEOUTS === '1'; + export function createSidecarProxy({ name, prefix, @@ -142,10 +155,15 @@ export function createSidecarProxy({ the 60s default drop. */ const server = ctx.env as { timeout?: (req: Request, seconds: number) => void } | undefined; - try { - server?.timeout?.(ctx.req.raw, timeoutSeconds ?? 0); - } catch { - /* no per-request timeout available */ + // `0` disables the idle timeout. With the switch on, an undeclared plugin falls back to the server's + // own 60s default by not being touched at all. + const inbound = TIMEOUTS_ON ? timeoutSeconds : (timeoutSeconds ?? 0); + if (inbound !== undefined) { + try { + server?.timeout?.(ctx.req.raw, inbound); + } catch { + /* no per-request timeout available */ + } } const method = ctx.req.method; @@ -228,7 +246,7 @@ export function createSidecarProxy({ headers, body, duplex: 'half', - timeout: false, + ...(TIMEOUTS_ON ? {} : { timeout: false }), }; let upstream: Response;