fix(dev): prevent duplicate backend launch and forward shutdown signals

This commit is contained in:
2026-10-07 11:01:18 +08:00
parent e50bed9ad8
commit 960af8d40a
3 changed files with 154 additions and 3 deletions
+23 -3
View File
@@ -1,8 +1,9 @@
#!/usr/bin/env node
// backend: 运行带 Air 热加载的 Go control-plane。
import { spawn } from "node:child_process";
import { readFileSync, existsSync } from "node:fs";
import { readFileSync, existsSync, mkdirSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { constants } from "node:os";
import path from "node:path";
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
@@ -40,9 +41,28 @@ if (!overrides.LOG_LEVEL) overrides.LOG_LEVEL = "debug";
if (!overrides.NATIVE_GATEWAY_ENDPOINT) overrides.NATIVE_GATEWAY_ENDPOINT = "http://127.0.0.1:28187";
const env = { ...process.env, ...overrides };
const air = spawn("air", ["-c", ".air.toml", ...process.argv.slice(2)], {
const lockDir = path.join(root, ".data");
mkdirSync(lockDir, { recursive: true });
// flock 持有锁直到 Air 及其子进程退出,拒绝重复启动,不争抢同一个程序文件。
const air = spawn("flock", [
"--no-fork", "--nonblock", "--conflict-exit-code", "73",
path.join(lockDir, "dev-backend.lock"),
"air", "-c", ".air.toml", ...process.argv.slice(2),
], {
cwd: root,
env,
stdio: "inherit",
});
air.on("exit", (code) => process.exit(code ?? 0));
for (const signal of ["SIGINT", "SIGTERM"]) {
process.on(signal, () => air.kill(signal));
}
air.on("error", (error) => {
console.error(`[dev-backend] 启动失败:${error.message}`);
process.exit(1);
});
air.on("exit", (code, signal) => {
if (code === 73) {
console.error("[dev-backend] 后台已在运行,拒绝重复启动。请停止原进程后再重启。");
}
process.exit(code ?? (128 + constants.signals[signal]));
});