fix: harden dev stack process detection
This commit is contained in:
@@ -181,6 +181,61 @@ function isPidRunning(pid) {
|
||||
}
|
||||
}
|
||||
|
||||
function readProcessCommand(pid) {
|
||||
if (!pid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const result = spawnSync("ps", ["-p", String(pid), "-o", "command="], {
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
if (result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const command = result.stdout.trim();
|
||||
return command.length > 0 ? command : null;
|
||||
}
|
||||
|
||||
export function getServiceCommandMatchers(service) {
|
||||
switch (service.key) {
|
||||
case "temporal":
|
||||
return ["temporal", "server", "start-dev"];
|
||||
case "backend-api":
|
||||
return ["uvicorn", "app.main:app"];
|
||||
case "backend-worker":
|
||||
return ["app.workers.runner"];
|
||||
case "frontend":
|
||||
return ["next", "dev", "127.0.0.1", "3000"];
|
||||
default:
|
||||
return service.command.map((part) => path.basename(part));
|
||||
}
|
||||
}
|
||||
|
||||
export function isServiceProcessMatch(service, processCommand) {
|
||||
if (!processCommand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalizedCommand = processCommand.toLowerCase();
|
||||
return getServiceCommandMatchers(service).every((matcher) =>
|
||||
normalizedCommand.includes(matcher.toLowerCase()),
|
||||
);
|
||||
}
|
||||
|
||||
export function isServiceHealthy(service, { pid, processCommand, portOpen }) {
|
||||
if (!pid || !isServiceProcessMatch(service, processCommand)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (service.port) {
|
||||
return portOpen;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function removePidFile(pidFilePath) {
|
||||
if (fs.existsSync(pidFilePath)) {
|
||||
fs.unlinkSync(pidFilePath);
|
||||
@@ -309,6 +364,12 @@ async function stopService(config, service) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const processCommand = readProcessCommand(pid);
|
||||
if (!isServiceProcessMatch(service, processCommand)) {
|
||||
removePidFile(pidFilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
process.kill(-pid, "SIGTERM");
|
||||
for (let index = 0; index < 20; index += 1) {
|
||||
if (!isPidRunning(pid)) {
|
||||
@@ -430,10 +491,21 @@ async function printStatus() {
|
||||
const pidFilePath = getServicePidFile(config, service.key);
|
||||
const logFilePath = getServiceLogFile(config, service.key);
|
||||
const pid = readPid(pidFilePath);
|
||||
const running = pid ? isPidRunning(pid) : false;
|
||||
const processCommand =
|
||||
pid && isPidRunning(pid) ? readProcessCommand(pid) : null;
|
||||
const portOpen = service.port ? await isLocalPortBusy(service.port) : false;
|
||||
const running = isServiceHealthy(service, {
|
||||
pid,
|
||||
processCommand,
|
||||
portOpen,
|
||||
});
|
||||
if (!running && pid) {
|
||||
removePidFile(pidFilePath);
|
||||
}
|
||||
const displayPid = running ? pid : null;
|
||||
const portText = service.port ? ` port=${service.port}` : "";
|
||||
const logText = fs.existsSync(logFilePath) ? ` log=${logFilePath}` : "";
|
||||
console.log(`${service.key}: ${running ? "running" : "stopped"} pid=${pid ?? "-"}${portText}${logText}`);
|
||||
console.log(`${service.key}: ${running ? "running" : "stopped"} pid=${displayPid ?? "-"}${portText}${logText}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user