refactor(backend): drop dead SpawnFn alias + test Pi exit-handler cleanup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 21:09:49 +02:00
co-authored by Claude Opus 4.8
parent de7200f7dd
commit f4c6126270
2 changed files with 17 additions and 1 deletions
+2 -1
View File
@@ -10,13 +10,14 @@ export interface SessionRuntime {
child: ChildProcessWithoutNullStreams;
}
/** Injected test double signature: produce a child process, no args needed. */
type SpawnFn = () => ChildProcessWithoutNullStreams;
export class PiProcessManager {
private runtimes = new Map<string, SessionRuntime>();
private spawnFn: (sessionId: string, author: string) => ChildProcessWithoutNullStreams;
constructor(private cfg: AppConfig, opts?: { spawnFn?: () => ChildProcessWithoutNullStreams }) {
constructor(private cfg: AppConfig, opts?: { spawnFn?: SpawnFn }) {
if (opts?.spawnFn) {
this.spawnFn = () => opts.spawnFn!();
} else {
+15
View File
@@ -19,6 +19,21 @@ test("spawnFor avvia un runtime e il bridge emette il widget F1", async () => {
expect(mgr.count()).toBe(0);
});
test("l'exit del child rimuove il runtime dalla mappa (exit handler)", async () => {
const cfg = loadConfig({ THT_HARNESS_DIR: "../harness" });
const mgr = new PiProcessManager(cfg, { spawnFn: () => spawn("node", [FAKE, SCRIPT]) as any });
const rt = await mgr.spawnFor("exit-test", {});
expect(mgr.count()).toBe(1);
// Cause the child to exit on its own and await the 'exit' event (no teardown call).
const exited = new Promise<void>((res) => rt.child.on("exit", () => res()));
rt.child.kill();
await exited;
// Let the manager's registered exit handler run.
await new Promise((res) => setImmediate(res));
expect(mgr.count()).toBe(0);
expect(mgr.get("exit-test")).toBeUndefined();
});
test("oltre maxPiProcesses solleva errore", async () => {
const cfg = { ...loadConfig({}), maxPiProcesses: 1 };
const mgr = new PiProcessManager(cfg, { spawnFn: () => spawn("node", [FAKE, SCRIPT]) as any });