From ee3546a6cedd044cbbb45a3937868f8b7a416d08 Mon Sep 17 00:00:00 2001 From: Ravi Tharuma <25951435+RaviTharuma@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:56:02 +0200 Subject: [PATCH] perf: reduce long-context request copies (#7862) Co-authored-by: Ravi Tharuma --- src/app/api/v1/chat/completions/route.ts | 5 +- .../chat-completions-parse-once-7847.test.ts | 112 ++++++++++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 tests/unit/chat-completions-parse-once-7847.test.ts diff --git a/src/app/api/v1/chat/completions/route.ts b/src/app/api/v1/chat/completions/route.ts index 2915d4730b..d2ce928a65 100644 --- a/src/app/api/v1/chat/completions/route.ts +++ b/src/app/api/v1/chat/completions/route.ts @@ -65,7 +65,7 @@ export async function POST(request) { } // Heap-pressure-aware admission: shed a large body with 503 (or 413 if pathological) - // BEFORE the request is cloned + JSON-parsed below. A large coding-agent compact body + // BEFORE the request is JSON-parsed below. A large coding-agent compact body // amplifies into hundreds of MB of transient JS objects on the combo path; under a // burst of concurrent compacts that stacks past the V8 heap ceiling and OOM-crashes the // whole process. Shedding the marginal request here turns a pod-wide crash into a single @@ -90,8 +90,7 @@ export async function POST(request) { // residency on the hot path and fed the OOM crash-loop (#4380). let parsedBody = null; try { - const cloned = request.clone(); - parsedBody = await cloned.json().catch(() => null); + parsedBody = await request.json().catch(() => null); if (parsedBody) { const { blocked, result } = injectionGuard(parsedBody); if (blocked) { diff --git a/tests/unit/chat-completions-parse-once-7847.test.ts b/tests/unit/chat-completions-parse-once-7847.test.ts new file mode 100644 index 0000000000..9b61a3a025 --- /dev/null +++ b/tests/unit/chat-completions-parse-once-7847.test.ts @@ -0,0 +1,112 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +// #7847: /v1/chat/completions already threads its parsed body into handleChat, so cloning +// the Request before parsing tees and retains an unused serialized-body branch. These tests +// pin the memory-sensitive contract: consume the original body once without cloning it. + +const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-chat-parse-once-7847-")); +process.env.DATA_DIR = TEST_DATA_DIR; + +const core = await import("../../src/lib/db/core.ts"); +const chatRoute = await import("../../src/app/api/v1/chat/completions/route.ts"); +const { resolveChatRequestBody } = await import("../../src/sse/handlers/requestBody.ts"); + +function makeCountingRequest(body: string) { + const request = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, + }); + + let jsonCalls = 0; + let cloneCalls = 0; + const originalJson = request.json.bind(request); + const originalClone = request.clone.bind(request); + + Object.defineProperties(request, { + json: { + value: async () => { + jsonCalls++; + return originalJson(); + }, + }, + clone: { + value: () => { + cloneCalls++; + return originalClone(); + }, + }, + }); + + return { + request, + jsonCalls: () => jsonCalls, + cloneCalls: () => cloneCalls, + }; +} + +function validBody(stream: boolean) { + return JSON.stringify({ + model: "openai/gpt-4.1", + messages: [{ role: "user", content: "Reply with OK only." }], + stream, + }); +} + +test("#7847 non-streaming requests parse the original body once without cloning", async () => { + const counting = makeCountingRequest(validBody(false)); + + await chatRoute.POST(counting.request); + + assert.equal(counting.jsonCalls(), 1, "the original request must be parsed exactly once"); + assert.equal(counting.cloneCalls(), 0, "the request body stream must not be teed"); +}); + +test("#7847 streaming requests parse the original body once without cloning", async () => { + const counting = makeCountingRequest(validBody(true)); + + const response = await chatRoute.POST(counting.request); + await response.text(); + + assert.equal(counting.jsonCalls(), 1, "early keepalive must reuse the parsed body"); + assert.equal(counting.cloneCalls(), 0, "streaming must not retain an unread body branch"); +}); + +test("#7847 malformed JSON still returns 400 after the original body is consumed", async () => { + const counting = makeCountingRequest('{"model":'); + + const response = await chatRoute.POST(counting.request); + + assert.equal(response.status, 400); + assert.equal(counting.cloneCalls(), 0, "invalid JSON must not require cloning the body stream"); +}); + +test("#7847 downstream body resolution preserves the parsed object's identity", async () => { + const parsedBody = { + model: "openai/gpt-4.1", + messages: [{ role: "user", content: "identity sentinel" }], + }; + let downstreamJsonCalls = 0; + + const resolved = await resolveChatRequestBody( + { + json: async () => { + downstreamJsonCalls++; + return { unexpected: true }; + }, + }, + parsedBody + ); + + assert.equal(resolved, parsedBody, "downstream must reuse the exact parsed object"); + assert.equal(downstreamJsonCalls, 0, "downstream must not parse or materialize another body"); +}); + +test.after(() => { + core.resetDbInstance(); + fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true }); +});