Files
zesdex/apps/packages/infrastructure/src/bgbash/job.ts
T

66 lines
1.7 KiB
TypeScript

/**
* Background bash job — spawns a `bash -c` subprocess and tracks its life.
* Mirrors `apps/infrastructure/src/bgbash/job.rs`.
*/
import { spawn, type ChildProcess } from "node:child_process";
import { randomUUID } from "node:crypto";
/** A handle to a spawned background bash job. */
export class BashJob {
readonly id: string;
readonly command: string;
private process: ChildProcess | null = null;
private cancelled = false;
private finished = false;
constructor(command: string) {
this.id = randomUUID();
this.command = command;
}
/** Spawn the `bash -c` child process and begin tracking it. */
start(): void {
const child = spawn("bash", ["-c", this.command], {
stdio: ["ignore", "pipe", "pipe"],
});
this.process = child;
// Drain stdout/stderr so the process doesn't block on a full pipe, and
// mark finished when it exits.
child.stdout?.resume();
child.stderr?.resume();
child.on("exit", () => {
this.finished = true;
});
child.on("error", () => {
this.finished = true;
});
}
/** Cancel the job: set the cancelled flag and kill the child process. */
cancel(): void {
this.cancelled = true;
if (this.process && !this.finished) {
try {
this.process.kill("SIGKILL");
} catch {
/* already gone */
}
}
}
/** Whether the job is currently running. */
isRunning(): boolean {
if (this.cancelled || this.finished) return false;
if (!this.process) return false;
return this.process.exitCode === null && !this.finished;
}
}
/** Spawn a background bash job and return its handle (node-side). */
export function spawnBashJob(command: string): BashJob {
const job = new BashJob(command);
job.start();
return job;
}