Files
pi-agent-integrated/scripts/storage-maintenance.test.mjs
T

93 lines
3.6 KiB
JavaScript

import assert from "node:assert/strict";
import { existsSync, mkdirSync, mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { maintainStorage } from "./storage-maintenance.mjs";
function createFile(path, bytes = 2048) {
mkdirSync(join(path, ".."), { recursive: true });
writeFileSync(path, Buffer.alloc(bytes));
}
function createCheckpoint(root, id, modifiedAt) {
const checkpoint = join(root, "home", ".pi", "agent", "ayu", "checkpoints", "sessions", id);
const objectDir = join(checkpoint, ".git", "objects", "ab");
mkdirSync(objectDir, { recursive: true });
createFile(join(objectDir, "object"));
createFile(join(checkpoint, "manifest.json"), 64);
for (const path of [join(objectDir, "object"), objectDir, join(checkpoint, ".git", "objects"), join(checkpoint, ".git"), join(checkpoint, "manifest.json"), checkpoint]) {
utimesSync(path, modifiedAt, modifiedAt);
}
return checkpoint;
}
test("automatic maintenance bounds caches and removes only expired orphan checkpoints", (t) => {
const root = mkdtempSync(join(tmpdir(), "pi-storage-maintenance-"));
const dataDir = join(root, "data");
const now = new Date("2026-07-31T00:00:00Z");
const old = new Date(now.getTime() - 8 * 24 * 60 * 60 * 1000);
const recent = new Date(now.getTime() - 24 * 60 * 60 * 1000);
t.after(() => rmSync(root, { recursive: true, force: true }));
const nextDev = join(root, "pi-web", ".next", "dev");
const nextCache = join(root, "pi-web", ".next", "cache");
const npmCache = join(dataDir, "cache", "npm");
createFile(join(nextDev, "large.bin"));
createFile(join(nextCache, "large.bin"));
createFile(join(npmCache, "large.bin"));
const sessions = join(dataDir, "agent", "sessions");
createFile(join(sessions, "live-session.jsonl"), 16);
const liveCheckpoint = createCheckpoint(dataDir, "live-session", old);
const expiredOrphan = createCheckpoint(dataDir, "expired-orphan", old);
const recentOrphan = createCheckpoint(dataDir, "recent-orphan", recent);
const compacted = [];
const result = maintainStorage({
mode: "auto",
rootDir: root,
dataDir,
nowMs: now.getTime(),
env: {
PI_STORAGE_NEXT_DEV_MAX_MB: "0.001",
PI_STORAGE_NEXT_CACHE_MAX_MB: "0.001",
PI_STORAGE_NPM_CACHE_MAX_MB: "0.001",
PI_STORAGE_ORPHAN_GRACE_DAYS: "7",
PI_STORAGE_REWIND_GC_OBJECTS: "1",
},
compactCheckpoint(path) {
compacted.push(path);
},
});
assert.equal(existsSync(nextDev), false);
assert.equal(existsSync(nextCache), false);
assert.equal(existsSync(npmCache), false);
assert.equal(existsSync(expiredOrphan), false);
assert.equal(existsSync(recentOrphan), true);
assert.equal(existsSync(liveCheckpoint), true);
assert.deepEqual(new Set(compacted), new Set([recentOrphan, liveCheckpoint]));
assert.ok(result.reclaimedBytes > 0);
});
test("clean mode removes every orphan while preserving live checkpoints", (t) => {
const root = mkdtempSync(join(tmpdir(), "pi-storage-clean-"));
const dataDir = join(root, "data");
t.after(() => rmSync(root, { recursive: true, force: true }));
createFile(join(dataDir, "agent", "sessions", "live-session.jsonl"), 16);
const liveCheckpoint = createCheckpoint(dataDir, "live-session", new Date());
const orphanCheckpoint = createCheckpoint(dataDir, "orphan-session", new Date());
maintainStorage({
mode: "clean",
rootDir: root,
dataDir,
env: { PI_STORAGE_REWIND_GC_OBJECTS: "999999" },
});
assert.equal(existsSync(liveCheckpoint), true);
assert.equal(existsSync(orphanCheckpoint), false);
});