chore: checkpoint before performance tuning
This commit is contained in:
+53
-2
@@ -1,4 +1,4 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { repoRoot, rootPath } from "./config";
|
||||
@@ -12,6 +12,9 @@ export interface JobRecord {
|
||||
status: JobStatus;
|
||||
command: string[];
|
||||
cwd: string;
|
||||
runner: "local" | "docker";
|
||||
runnerPid?: number | null;
|
||||
runnerContainer?: string | null;
|
||||
createdAt: string;
|
||||
startedAt: string | null;
|
||||
finishedAt: string | null;
|
||||
@@ -21,6 +24,11 @@ export interface JobRecord {
|
||||
note: string;
|
||||
}
|
||||
|
||||
export interface StartJobOptions {
|
||||
runner?: "local" | "docker";
|
||||
dockerImage?: string;
|
||||
}
|
||||
|
||||
function jobsDir(): string {
|
||||
const dir = rootPath(".state", "jobs");
|
||||
mkdirSync(dir, { recursive: true });
|
||||
@@ -48,16 +56,20 @@ export function listJobs(): JobRecord[] {
|
||||
.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
||||
}
|
||||
|
||||
export function startJob(name: string, command: string[], note: string): JobRecord {
|
||||
export function startJob(name: string, command: string[], note: string, options: StartJobOptions = {}): JobRecord {
|
||||
const id = `${name}_${new Date().toISOString().replace(/[-:.TZ]/g, "")}_${Math.random().toString(16).slice(2, 8)}`;
|
||||
const stdoutFile = rootPath(".state", "jobs", `${id}.stdout.log`);
|
||||
const stderrFile = rootPath(".state", "jobs", `${id}.stderr.log`);
|
||||
const runner = options.runner ?? "local";
|
||||
const job: JobRecord = {
|
||||
id,
|
||||
name,
|
||||
status: "queued",
|
||||
command,
|
||||
cwd: repoRoot,
|
||||
runner,
|
||||
runnerPid: null,
|
||||
runnerContainer: null,
|
||||
createdAt: new Date().toISOString(),
|
||||
startedAt: null,
|
||||
finishedAt: null,
|
||||
@@ -67,12 +79,50 @@ export function startJob(name: string, command: string[], note: string): JobReco
|
||||
note,
|
||||
};
|
||||
writeJob(job);
|
||||
if (runner === "docker") {
|
||||
const containerName = `unidesk-job-runner-${id}`.replace(/[^A-Za-z0-9_.-]/g, "-").slice(0, 120);
|
||||
job.runnerContainer = containerName;
|
||||
writeJob(job);
|
||||
const dockerArgs = [
|
||||
"run",
|
||||
"-d",
|
||||
"--rm",
|
||||
"--name",
|
||||
containerName,
|
||||
"-v",
|
||||
"/var/run/docker.sock:/var/run/docker.sock",
|
||||
"-v",
|
||||
`${repoRoot}:${repoRoot}`,
|
||||
"-w",
|
||||
repoRoot,
|
||||
"--entrypoint",
|
||||
"bun",
|
||||
options.dockerImage ?? "unidesk-codex-queue:latest",
|
||||
rootPath("scripts", "cli.ts"),
|
||||
"internal",
|
||||
"run-job",
|
||||
id,
|
||||
];
|
||||
const result = spawnSync("docker", dockerArgs, { cwd: repoRoot, encoding: "utf8" });
|
||||
if (result.status !== 0) {
|
||||
job.status = "failed";
|
||||
job.startedAt = new Date().toISOString();
|
||||
job.finishedAt = new Date().toISOString();
|
||||
job.exitCode = result.status ?? 127;
|
||||
writeFileSync(stderrFile, result.stderr || result.error?.message || "failed to start docker job runner\n", "utf8");
|
||||
writeFileSync(stdoutFile, result.stdout || "", "utf8");
|
||||
writeJob(job);
|
||||
}
|
||||
return job;
|
||||
}
|
||||
const child = spawn(process.execPath, [rootPath("scripts", "cli.ts"), "internal", "run-job", id], {
|
||||
cwd: repoRoot,
|
||||
detached: true,
|
||||
stdio: "ignore",
|
||||
env: process.env,
|
||||
});
|
||||
job.runnerPid = child.pid ?? null;
|
||||
writeJob(job);
|
||||
child.unref();
|
||||
return job;
|
||||
}
|
||||
@@ -80,6 +130,7 @@ export function startJob(name: string, command: string[], note: string): JobReco
|
||||
export async function runJob(id: string): Promise<JobRecord> {
|
||||
const job = readJob(id);
|
||||
job.status = "running";
|
||||
job.runnerPid = process.pid;
|
||||
job.startedAt = new Date().toISOString();
|
||||
writeJob(job);
|
||||
const exitCode = await runCommandToFiles(job.command, job.cwd, job.stdoutFile, job.stderrFile);
|
||||
|
||||
Reference in New Issue
Block a user