fix(sessions): preserve lifecycle headers across short reads (#109205)

This commit is contained in:
Wynne668
2026-07-16 15:09:06 -07:00
committed by GitHub
parent 31b3020372
commit 13ca829e2e
2 changed files with 29 additions and 10 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
// Session lifecycle timestamps prefer store metadata and fall back to transcript headers.
import fs from "node:fs";
import { readFileWindowFullySync } from "../../infra/file-read.js";
import { asDateTimestampMs } from "../../shared/number-coercion.js";
import { canonicalizeMainSessionAlias } from "./main-session.js";
import {
@@ -111,7 +112,7 @@ function readFirstLine(filePath: string): string | undefined {
const fd = fs.openSync(filePath, "r");
try {
const buffer = Buffer.alloc(8192);
const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, 0);
const bytesRead = readFileWindowFullySync(fd, buffer, 0);
if (bytesRead <= 0) {
return undefined;
}
+27 -9
View File
@@ -302,16 +302,34 @@ describe("session lifecycle timestamps", () => {
"utf8",
);
const timestamps = resolveSessionLifecycleTimestamps({
storePath,
entry: {
sessionId: "legacy-session",
sessionFile,
updatedAt: Date.parse("2026-04-25T08:00:00.000Z"),
},
});
const realReadSync = fs.readSync.bind(fs);
let shortReadCalls = 0;
const readSpy = vi.spyOn(fs, "readSync").mockImplementation(((
fd: number,
buffer: NodeJS.ArrayBufferView,
offset: number,
length: number,
position: fs.ReadPosition | null,
) => {
shortReadCalls += 1;
return realReadSync(fd, buffer, offset, Math.min(length, 16), position);
}) as typeof fs.readSync);
expect(timestamps.sessionStartedAt).toBe(Date.parse(headerTimestamp));
try {
const timestamps = resolveSessionLifecycleTimestamps({
storePath,
entry: {
sessionId: "legacy-session",
sessionFile,
updatedAt: Date.parse("2026-04-25T08:00:00.000Z"),
},
});
expect(timestamps.sessionStartedAt).toBe(Date.parse(headerTimestamp));
expect(shortReadCalls).toBeGreaterThan(1);
} finally {
readSpy.mockRestore();
}
} finally {
await fsPromises.rm(dir, { recursive: true, force: true });
}