fix(stats): avoided macos stats sync worker abort

Kept the documented workers: 1 path inline and defaulted macOS stats sync to that serial parser path so /stats dashboard launches do not re-enter Bun workers on macOS.

Fixes #3733
This commit is contained in:
roboomp
2026-06-28 16:21:59 +00:00
parent 2622ab13fe
commit b48d488f2c
3 changed files with 144 additions and 33 deletions
+91
View File
@@ -0,0 +1,91 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "bun:test";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { syncAllSessions } from "@oh-my-pi/omp-stats/aggregator";
import { closeDb, getOverallStats } from "@oh-my-pi/omp-stats/db";
import { getAgentDir, getSessionsDir, setAgentDir, TempDir } from "@oh-my-pi/pi-utils";
const originalConfigDir = process.env.PI_CONFIG_DIR;
const originalAgentDir = getAgentDir();
let tempDir: TempDir | null = null;
beforeEach(() => {
tempDir = TempDir.createSync("@pi-stats-sync-serial-");
const configDir = path.relative(os.homedir(), tempDir.join("config"));
process.env.PI_CONFIG_DIR = configDir;
setAgentDir(tempDir.join("agent"));
});
afterEach(() => {
vi.restoreAllMocks();
closeDb();
if (originalConfigDir === undefined) {
delete process.env.PI_CONFIG_DIR;
} else {
process.env.PI_CONFIG_DIR = originalConfigDir;
}
setAgentDir(originalAgentDir);
tempDir?.removeSync();
tempDir = null;
});
async function writeSessionFile(): Promise<void> {
const sessionDir = path.join(getSessionsDir(), "--tmp--sync-serial");
await fs.mkdir(sessionDir, { recursive: true });
const timestamp = new Date().toISOString();
const sessionFile = path.join(sessionDir, "session.jsonl");
const assistant = {
type: "message",
id: "assistant-1",
parentId: null,
timestamp,
message: {
role: "assistant",
content: [{ type: "text", text: "ok" }],
api: "openai-responses",
provider: "openai",
model: "gpt-5.4",
usage: {
input: 1,
output: 2,
cacheRead: 0,
cacheWrite: 0,
totalTokens: 3,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
},
stopReason: "stop",
timestamp: Date.now(),
duration: 10,
ttft: 5,
},
};
await Bun.write(sessionFile, `${JSON.stringify(assistant)}\n`);
}
describe("stats sync serial mode", () => {
it("honors workers: 1 without spawning a worker", async () => {
await writeSessionFile();
const workerSpy = vi.spyOn(globalThis, "Worker");
const synced = await syncAllSessions({ workers: 1 });
const overall = getOverallStats();
expect(synced.files).toBe(1);
expect(overall.totalRequests).toBe(1);
expect(workerSpy).not.toHaveBeenCalled();
});
it("uses the serial parser by default on macOS", async () => {
await writeSessionFile();
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
const workerSpy = vi.spyOn(globalThis, "Worker");
const synced = await syncAllSessions();
const overall = getOverallStats();
expect(synced.files).toBe(1);
expect(overall.totalRequests).toBe(1);
expect(workerSpy).not.toHaveBeenCalled();
});
});