mirror of
https://github.com/wassname/talk.git
synced 2026-09-12 13:01:11 +08:00
Watcher infrastructure (#1724)
* wip * Adding chokidar and types * specifiying build tasks * new structure, new types, executor and watchers * Adding log * Fully implemented watchers * adapt vscode launc * Add .babelrc.js to toplevel tsconfig project * Typo * Get schema path from .graphqlconfig * Use watcher binary * Add joi validation to watcher * Remove fb-watchman for now * Use correct ignore path * Fix dist folder * Allow setting watcher * Per default only spawn one process at a time * Support runOnInit * Rename RestartingExecutor to LongRunningExecutor * Use debounce instead of throttle * Remove console log * Debounce command execution * Simplify debounce * Watcher name change * Typos * Rename "watcher" root level config to "backend"
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { ChildProcess } from "child_process";
|
||||
import spawn from "cross-spawn";
|
||||
import { Cancelable, debounce } from "lodash";
|
||||
import { Executor } from "./types";
|
||||
|
||||
interface LongRunningExecutorOptions {
|
||||
args?: ReadonlyArray<string>;
|
||||
|
||||
// Specify the period in which the process is restarted at max once.
|
||||
debounce?: number;
|
||||
}
|
||||
|
||||
export default class LongRunningExecutor implements Executor {
|
||||
private cmd: string;
|
||||
private args?: ReadonlyArray<string>;
|
||||
private process: ChildProcess | null = null;
|
||||
private isRunning: boolean = false;
|
||||
private shouldRestart: boolean = false;
|
||||
private restartDebounced: (() => void) & Cancelable;
|
||||
|
||||
constructor(cmd: string, opts: LongRunningExecutorOptions = {}) {
|
||||
this.cmd = cmd;
|
||||
this.args = opts.args;
|
||||
this.restartDebounced = debounce(
|
||||
() => this.restart(),
|
||||
opts.debounce || 500
|
||||
);
|
||||
}
|
||||
|
||||
private spawnProcess() {
|
||||
this.isRunning = true;
|
||||
this.process = spawn(this.cmd, this.args as string[], {
|
||||
stdio: "inherit",
|
||||
// Have all child processes in their own group.
|
||||
// See `process.kill` below.
|
||||
detached: true,
|
||||
shell: !this.args,
|
||||
});
|
||||
|
||||
this.process!.on("exit", (code: number) => {
|
||||
this.isRunning = false;
|
||||
|
||||
if (code !== 0 && code !== null) {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.error(`Exit code returned ${code}`);
|
||||
return;
|
||||
}
|
||||
if (this.shouldRestart) {
|
||||
this.spawnProcess();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private restart(): void {
|
||||
this.shouldRestart = true;
|
||||
// Using the `-` will kill all child procceses in the group.
|
||||
// See: https://azimi.me/2014/12/31/kill-child_process-node-js.html
|
||||
process.kill(-this.process!.pid, "SIGTERM");
|
||||
}
|
||||
|
||||
private kill(): void {
|
||||
this.shouldRestart = false;
|
||||
// Using the `-` will kill all child procceses in the group.
|
||||
// See: https://azimi.me/2014/12/31/kill-child_process-node-js.html
|
||||
process.kill(-this.process!.pid, "SIGTERM");
|
||||
}
|
||||
|
||||
// This is called before watching starts.
|
||||
public onInit(): void {
|
||||
this.spawnProcess();
|
||||
}
|
||||
|
||||
// This is called before exiting.
|
||||
public onCleanup() {
|
||||
this.restartDebounced.cancel();
|
||||
if (this.isRunning) {
|
||||
this.kill();
|
||||
}
|
||||
}
|
||||
|
||||
public execute(filePath: string) {
|
||||
if (this.isRunning) {
|
||||
this.restartDebounced();
|
||||
return;
|
||||
}
|
||||
this.spawnProcess();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user