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:
@@ -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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user