mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 10:26:26 +01:00
The file gateway charged reserveBodyRead(declaredBytes * 15) and held the whole request as four copies at once: the raw buffer, the decoded string, the JSON.stringify string, and the UTF-8 write buffer. At the production body cap, that charge alone (about 150 MiB) exceeded the whole 64 MiB inflight bound, so a body at the cap always got a 503 on an idle gateway. An unknown-length request (no Content-Length header, for example a chunked request) hit the same charge, because declaredBodyBytes fell back to the body cap for it. Stream the JSON request file to disk instead of building it in memory first. Write the small envelope fields with JSON.stringify, then stream the decoded body through a bounded escape-and-write loop, one fixed-size slice at a time, then the closing fields. This removes the whole-escaped-string copy and the whole write-buffer copy, so the reserve factor drops from 15 to 4 and covers only the raw buffer and the decoded string. A separate fixed term, FILE_GATEWAY_BODY_RESERVE_EXTRA_BYTES, covers the one bounded escape slice the write loop holds at a time. Grow the body read for an unknown-length request instead of preallocating the body cap: accumulate chunks in an array and join them once at the end, capped at the declared body cap, so a 200-byte chunked request no longer allocates 10 MiB. readBody now takes the declared length as null instead of a sentinel value, so a caller can tell a real declared length from an unknown one. The duplex gateway keeps its existing charge (the declared length plus one frame's worth of headroom); only the null-based sentinel changed, not the charge value. Verified: a body of 10,485,760 bytes and a request with no Content-Length header both now reach the host worker instead of getting a 503, at the production body cap and inflight bound. Both new tests fail with 503 against the prior commit and pass against this change. All 43 tests in sandbox-callback-bridge.test.ts, 19 in duplex-bridge-local-e2e.test.ts, 136 in execution-target-sandbox.test.ts, and 2 in execution-target-ssh-buffer.test.ts pass. npx tsc --noEmit on packages/adapter-utils is clean. Co-authored-by: Paperclip <noreply@paperclip.ing>