stopJob
uses node:path
Stop a running job, and what it runs (its process group): asked to (SIGTERM), then made to (SIGKILL) if it hasn't
ended in grace ms. Its end says it was stopped. The job as it is then.
import { readJob } from "#codebase/tcmts/cli/mcp"; import type { JobEnd, JobState } from "#codebase/tcmts/cli/mcp"; import fs from "node:fs"; import path from "node:path"; export async function stopJob( dir: string, id: number, grace = 5000, ): Promise<JobState | undefined> { const job = readJob(dir, id); if (!job || job.done || job.lost) return job; const signal = (s: NodeJS.Signals) => { try { process.kill(-job.pid, s); } catch { try { process.kill(job.pid, s); } catch {} } }; const exit = path.join(dir, `${id}.exit`); signal("SIGTERM"); for (const until = Date.now() + grace; Date.now() < until && !fs.existsSync(exit);) await new Promise((r) => setTimeout(r, 100)); if (!fs.existsSync(exit)) signal("SIGKILL"); let end: JobEnd = { code: 143, at: Date.now() }; try { end = JSON.parse(fs.readFileSync(exit, "utf8")) as JobEnd; } catch {} fs.writeFileSync(exit, JSON.stringify({ ...end, stopped: true })); return readJob(dir, id); }