From d19f649a55055c936d5599e4143ced70292339ee Mon Sep 17 00:00:00 2001 From: modeco80 Date: Sat, 2 Nov 2024 02:52:43 -0400 Subject: [PATCH] add a interface for process launching This is to allow external usage of the library to control process launching (and, for one example, place processes we launch into special cgroups.) --- src/DefaultProcess.ts | 44 +++++++++++++++++++++++++++++++++++++++++ src/ProcessInterface.ts | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/DefaultProcess.ts create mode 100644 src/ProcessInterface.ts diff --git a/src/DefaultProcess.ts b/src/DefaultProcess.ts new file mode 100644 index 0000000..806b39d --- /dev/null +++ b/src/DefaultProcess.ts @@ -0,0 +1,44 @@ +// Default process implementation. +// This uses execa like the current code, but conforms to our abstration :) + +import EventEmitter from "events"; +import { IProcess, IProcessLauncher, ProcessLaunchOptions } from "./ProcessInterface"; +import { execaCommand } from "execa"; +import { Readable, Writable } from "stream"; + + +class DefaultProcess extends EventEmitter implements IProcess { + private process; + stdin: Writable | null = null; + stdout: Readable | null = null; + stderr: Readable | null = null; + + constructor(command: string, opts?: ProcessLaunchOptions) { + super(); + + this.process = execaCommand(command, opts); + + this.stdin = this.process.stdin; + this.stdout = this.process.stdout; + this.stderr = this.process.stderr; + + let self = this; + this.process.on('spawn', () => { + self.emit('spawn'); + }); + + this.process.on('exit', (code) => { + self.emit('exit', code); + }); + } + + kill(signal?: number | NodeJS.Signals): boolean { + return this.process.kill(signal); + } +} + +export class DefaultProcessLauncher implements IProcessLauncher { + launch(command: string, opts?: ProcessLaunchOptions | undefined): IProcess { + return new DefaultProcess(command, opts); + } +} \ No newline at end of file diff --git a/src/ProcessInterface.ts b/src/ProcessInterface.ts new file mode 100644 index 0000000..7d46b59 --- /dev/null +++ b/src/ProcessInterface.ts @@ -0,0 +1,36 @@ +import {type Stream, EventEmitter, Readable, Writable} from 'node:stream'; + +export type StdioOption = + | 'pipe' + | 'overlapped' + | 'ipc' + | 'ignore' + | 'inherit' + | Stream + | number + | undefined; + +// subset of options. FIXME: Add more!!! +export interface ProcessLaunchOptions { + stdin?: StdioOption, + stdout?: StdioOption, + stderr?: StdioOption +} + +export interface IProcess extends EventEmitter { + stdin: Writable | null; + stdout: Readable | null; + stderr: Readable | null; + + + // Escape hatch; only use this if you have no choice + //native() : any; + + kill(signal?: number | NodeJS.Signals): boolean; + +} + +// Launches a processs. +export interface IProcessLauncher { + launch(command: string, opts?: ProcessLaunchOptions) : IProcess; +} \ No newline at end of file