startJob

tcmts.cli.mcp.startJob · #pjyhxm4t · term · runs on the server

uses node:fs

Start a background job in dir (a session's jobs directory, jobsDirFor): runJob, detached (a process group of its own, with nothing tying it to this process), running run.cmd in run.cwd with run.env, or asking it run.call. Its record, output and end are files there, so it runs on when the server that started it stops (tcm replaced), and the next one follows it. Ids go on from the directory's last, whatever's been cleared away since; finished jobs' files a day old are cleared away first (sweepJobs).

import { lastJobId, runJob, sweepJobs } from "#codebase/tcmts/cli/mcp";
import type { Job } from "#codebase/tcmts/cli/mcp";
import { spawn } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

export function startJob(
  dir: string,
  job: { argv: string[]; tool?: string },
  run: {
    cmd: string[];
    cwd: string;
    env: NodeJS.ProcessEnv;
    call?: { name: string; arguments: Record<string, unknown> };
  },
): number {
  fs.mkdirSync(dir, { recursive: true });
  sweepJobs(dir);
  const id = lastJobId(dir) + 1;
  fs.writeFileSync(path.join(dir, "last"), String(id));
  const file = (ext: string) => path.join(dir, `${id}.${ext}`);
  fs.writeFileSync(file("log"), "");
  const spec = {
    cmd: run.cmd,
    cwd: run.cwd,
    log: file("log"),
    exit: file("exit"),
    ...(run.call ? { call: run.call } : {}),
  };
  const child = spawn(
    process.execPath,
    [
      "-e",
      `(${runJob.toString()})(JSON.parse(process.argv[1]), { spawn: require("node:child_process").spawn, fs: require("node:fs") })`,
      JSON.stringify(spec),
    ],
    { cwd: run.cwd, env: run.env, detached: true, stdio: "ignore" },
  );
  child.unref();
  const record: Job = { ...job, started: Date.now(), pid: child.pid ?? 0, server: process.pid };
  fs.writeFileSync(file("json"), JSON.stringify(record));
  return id;
}

uses

used by