fix: finalize durable Pi lifecycle

This commit is contained in:
2026-08-04 21:34:08 +02:00
parent 5ba2821a1b
commit a368889838
20 changed files with 1016 additions and 147 deletions
+56 -1
View File
@@ -1,5 +1,5 @@
import { test, expect } from "vitest";
import { existsSync, mkdtempSync, rmSync } from "node:fs";
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { MaintenanceBarrier } from "../src/runtime/maintenance-gate.js";
@@ -45,3 +45,58 @@ test("durable activation survives recreation and deactivation removes the marker
rmSync(directory, { recursive: true, force: true });
}
});
test("activation reconciles active state when directory fsync fails after marker rename", async () => {
const directory = mkdtempSync(join(tmpdir(), "tht-maintenance-activate-fsync-"));
const marker = join(directory, "maintenance.json");
try {
const gate = new MaintenanceBarrier(marker, {
syncDirectory() { throw new Error("injected post-rename fsync failure"); },
});
await expect(gate.activate()).rejects.toThrow(/post-rename fsync failure/);
expect(existsSync(marker)).toBe(true);
expect(gate.status()).toEqual({ active: true, admissions: 0 });
expect(gate.acquire()).toBeUndefined();
const recovered = new MaintenanceBarrier(marker);
expect(recovered.status()).toEqual({ active: true, admissions: 0 });
expect(recovered.acquire()).toBeUndefined();
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("deactivation reconciles inactive state when directory fsync fails after marker removal", async () => {
const directory = mkdtempSync(join(tmpdir(), "tht-maintenance-deactivate-fsync-"));
const marker = join(directory, "maintenance.json");
let failSync = false;
try {
const gate = new MaintenanceBarrier(marker, {
syncDirectory() {
if (failSync) throw new Error("injected post-remove fsync failure");
},
});
await gate.activate();
failSync = true;
expect(() => gate.deactivate()).toThrow(/post-remove fsync failure/);
expect(existsSync(marker)).toBe(false);
expect(gate.status()).toEqual({ active: false, admissions: 0 });
expect(gate.acquire()).toBeTypeOf("function");
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("status and admission recover from a persistent marker even when memory started inactive", () => {
const directory = mkdtempSync(join(tmpdir(), "tht-maintenance-reconcile-"));
const marker = join(directory, "maintenance.json");
try {
const gate = new MaintenanceBarrier(marker);
expect(gate.status().active).toBe(false);
writeFileSync(marker, '{"version":1,"active":true}\n', { mode: 0o600 });
expect(gate.status()).toEqual({ active: true, admissions: 0 });
expect(gate.acquire()).toBeUndefined();
} finally {
rmSync(directory, { recursive: true, force: true });
}
});