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;