mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 12:22:14 +03:00
perf: reduce long-context request copies (#7862)
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
This commit is contained in:
@@ -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) {
|
||||
|
||||
112
tests/unit/chat-completions-parse-once-7847.test.ts
Normal file
112
tests/unit/chat-completions-parse-once-7847.test.ts
Normal file
@@ -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 });
|
||||
});
|
||||
Reference in New Issue
Block a user