Public: anyone can read this; the crew can change it.

Hold an app awake while a proxied request waits for its answer #1293

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The proxy now holds an environment awake from the moment it passes a request until that request's answer begins, so a slow answer no longer gets its app put to sleep. I haven't run any of this. `test/apps-busy.test.ts` needs to listen on a socket, which my sandbox blocks (`EPERM`), and `tsc` couldn't find the `bun` types. I also never saw the new test fail without the change, so please run `bun te…

shipped production is serving it deploy 9e69a5f

opened this

The proxy now holds an environment awake from the moment it passes a request until that request's answer begins, so a slow answer no longer gets its app put to sleep. I haven't run any of this. test/apps-busy.test.ts needs to listen on a socket, which my sandbox blocks (EPERM), and tsc couldn't find the bun types. I also never saw the new test fail without the change, so please run bun test test/apps-busy.test.ts before merging.

  • What changed: holdRequest() in src/apps/runtime.ts counts requests still waiting for their answer. The proxy in src/apps/proxy.ts takes that hold just before it forwards the request and releases it when the answer's headers arrive or the fetch fails. src/apps/busy.ts gains a busy reason, request, which counts inside the same grace as the others, so a hung app still sleeps eventually.
  • Event streams: an event stream takes its own hold before the request hold is released, so there is no gap between the two.
  • Test: I added a test to test/apps-busy.test.ts with a /slow route that answers after 2 seconds, about three idle windows. It expects the answer to arrive and the app to still be running afterward. Without the hold, the sweep stops the app mid-request and the proxy returns an error instead.
  • Reuse: commit 7a4ba31 wasn't in my clone, so I rewrote the change from the description in #1274 rather than picking it up from there.
  • Left out: websocket handshakes go through the same hold, but I added no separate test for them.

Closes #1274

Approved

Does what the issue asks: a proxied request holds the environment busy until its answer begins, released exactly once on every path (success, fetch failure, event stream taking its own hold first). The hold sits inside the existing busy grace, so a hung app still sleeps. The test uses a 2 s answer against a 700 ms window, so it fails without the change. No new surface, no dependency, no security-relevant change (identity headers still stripped and re-set before the hold).

Two things I would do next: (1) the proxy.ts return now has a new Response( body, { shape that formatting would collapse onto one line; run the formatter. (2) Only the wait for headers is held; a long non-stream body download after that is not. If large slow downloads matter, release on body end rather than at headers.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs