music: 30-min per-request idle timeout for reindex/manifest (from-scratch builds)

A from-scratch rebuild holds the triggering request open for many minutes with
no bytes flowing, so both server hops' idle timeouts would drop it. Bun caps the
server-level idleTimeout at 255s, but server.timeout(req, seconds) allows more
per-request:
- sidecar Bun.serve: extend /reindex, /manifest, /reindex/stream to 1800s.
- platform proxy (music router): same, via the Bun server exposed as Hono's env.

Baseline idleTimeouts unchanged (sidecar 255, main server 60). The build always
completed in the background regardless; this keeps the request itself alive.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 15:23:27 +00:00
co-authored by Claude Opus 4.8
parent 43135865e2
commit de0642766c
2 changed files with 20 additions and 4 deletions
+12
View File
@@ -90,6 +90,18 @@ musicRouter.all('/*', async (ctx) => {
const subpath = url.pathname.slice(PREFIX.length) || '/';
const target = `${baseUrl}${subpath}${url.search}`;
// A from-scratch reindex holds this proxied connection open for minutes with no bytes flowing, which
// the main server's 60s idle timeout would drop. Extend it to 30 min for the build/progress endpoints
// (Bun passes the server as Hono's env). Matches the sidecar's own per-request extension.
if (subpath === '/reindex' || subpath === '/manifest' || subpath === '/reindex/stream') {
const server = ctx.env as { timeout?: (req: Request, seconds: number) => void } | undefined;
try {
server?.timeout?.(ctx.req.raw, 1800);
} catch {
/* older Bun / no per-request timeout — the build still completes in the background */
}
}
const range = ctx.req.header('range');
let upstream: Response;
try {
+8 -4
View File
@@ -74,12 +74,16 @@ const port = getFreePort();
const server = Bun.serve({
port,
hostname: '127.0.0.1',
// A blocking /reindex (esp. the one-time full rebuild) and long range/SSE reads far outlast Bun's
// default 10s request idle-timeout, which would drop them mid-flight. 255s is Bun's max; a build that
// still outruns it completes in the background anyway (the promise isn't cancelled by a closed socket).
// Bun caps the server-level idleTimeout at 255s. Keep it there as the baseline; the build/stream
// endpoints (which can idle for a whole from-scratch rebuild) extend it per-request via server.timeout.
idleTimeout: 255,
async fetch(req) {
async fetch(req, server) {
const url = new URL(req.url);
// A from-scratch reindex can take many minutes with no bytes flowing on the triggering request.
// Give the build-triggering + progress endpoints a 30-min idle timeout so they aren't dropped.
if (url.pathname === '/reindex' || url.pathname === '/manifest' || url.pathname === '/reindex/stream') {
server.timeout(req, 1800);
}
const json = (data: unknown, init?: ResponseInit) =>
new Response(JSON.stringify(data), { ...init, headers: { 'Content-Type': 'application/json', ...init?.headers } });