stopJob

tcmts.cli.mcp.stopJob · #pm6f5xuu · term · runs on the server

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);
}

uses

used by