Files
openclaw/extensions/codex/src/jsonl-lines.ts
T
WhatsSkiLL d4436e9a17 perf(codex): stream large CLI session JSONL scans (#115997)
* fix(codex): stream CLI session JSONL scans

* perf(codex): scan JSONL in bounded chunks

* perf(codex): keep small JSONL reads fast

* perf(codex): avoid rescanning long rollout records

* test(codex): prove streamed rollout recovery

* refactor(codex): isolate JSONL line scanning

* fix(codex): avoid env ratchet token in relay constant

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-30 02:35:41 +08:00

95 lines
2.7 KiB
TypeScript

import fs from "node:fs/promises";
const JSONL_STREAM_THRESHOLD_BYTES = 4 * 1024 * 1024;
const JSONL_READ_CHUNK_BYTES = 1024 * 1024;
export const JSONL_FIRST_LINE_CHUNK_BYTES = 64 * 1024;
export async function visitJsonlLines(
file: string,
visitor: (line: string) => boolean | void,
chunkBytes = JSONL_READ_CHUNK_BYTES,
): Promise<{ ok: boolean; lineCount: number }> {
let size: number;
try {
size = (await fs.stat(file)).size;
} catch {
return { ok: false, lineCount: 0 };
}
if (size <= JSONL_STREAM_THRESHOLD_BYTES) {
let content: string;
try {
content = await fs.readFile(file, "utf8");
} catch {
return { ok: false, lineCount: 0 };
}
if (content.length === 0) {
return { ok: true, lineCount: 0 };
}
let lineCount = 0;
for (const line of content.split(/\r?\n/u)) {
lineCount += 1;
if (visitor(line) === false) {
break;
}
}
return { ok: true, lineCount };
}
let handle: Awaited<ReturnType<typeof fs.open>>;
try {
handle = await fs.open(file, "r");
} catch {
return { ok: false, lineCount: 0 };
}
const buffer = Buffer.allocUnsafe(chunkBytes);
const decoder = new TextDecoder();
let pendingFragments: string[] = [];
let lineCount = 0;
try {
while (true) {
const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);
if (bytesRead === 0) {
break;
}
const content = decoder.decode(buffer.subarray(0, bytesRead), { stream: true });
let lineStart = 0;
while (true) {
const newline = content.indexOf("\n", lineStart);
if (newline === -1) {
break;
}
let rawLine = content.slice(lineStart, newline);
if (pendingFragments.length > 0) {
pendingFragments.push(rawLine);
rawLine = pendingFragments.join("");
pendingFragments = [];
}
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
lineCount += 1;
if (visitor(line) === false) {
return { ok: true, lineCount };
}
lineStart = newline + 1;
}
if (lineStart < content.length) {
pendingFragments.push(content.slice(lineStart));
}
}
const decoderTail = decoder.decode();
if (decoderTail.length > 0) {
pendingFragments.push(decoderTail);
}
if (pendingFragments.length > 0) {
const rawLine = pendingFragments.join("");
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
lineCount += 1;
visitor(line);
}
return { ok: true, lineCount };
} catch {
return { ok: false, lineCount: 0 };
} finally {
await handle.close().catch(() => undefined);
}
}