feat: complete notdienst planning, quick wins and notifications

This commit is contained in:
t.indorf
2026-10-12 15:34:09 +02:00
parent b915857951
commit 00f602a7aa
50 changed files with 2443 additions and 513 deletions
+58
View File
@@ -0,0 +1,58 @@
import { spawn } from "node:child_process";
let stopping = false,
worker,
restartTimer,
stopTimer;
const server = spawn(process.execPath, ["server.js"], { stdio: "inherit" });
function shutdown(code = 0) {
if (stopping) return;
stopping = true;
process.exitCode = code;
clearTimeout(restartTimer);
server.kill("SIGTERM");
worker?.kill("SIGTERM");
stopTimer = setTimeout(() => {
server.kill("SIGKILL");
worker?.kill("SIGKILL");
process.exit(code);
}, 4000);
stopTimer.unref();
Promise.all(
[server, worker]
.filter(Boolean)
.map((child) =>
child.exitCode !== null || child.signalCode !== null
? Promise.resolve()
: new Promise((resolve) => child.once("close", resolve)),
),
).then(() => {
clearTimeout(stopTimer);
process.exit(code);
});
}
function startWorker() {
if (stopping) return;
worker = spawn(process.execPath, ["scripts/notdienst-alarm-worker.mjs"], {
stdio: "inherit",
});
worker.on("close", () => {
if (stopping) return;
console.error(
"Notdienst-Hintergrundjob beendet; Neustart in fünf Sekunden.",
);
restartTimer = setTimeout(startWorker, 5000);
});
worker.on("error", () => {
if (!stopping)
console.error("Notdienst-Hintergrundjob konnte nicht starten.");
});
}
server.on("exit", (code) => shutdown(code ?? 1));
server.on("error", () => shutdown(1));
for (const signal of ["SIGTERM", "SIGINT"])
process.on(signal, () => shutdown(0));
if ((process.env.NOTDIENST_JOB_SECRET?.length ?? 0) >= 32) startWorker();
else
console.warn(
"Automatische Notdienst-Jobs deaktiviert: gültiges NOTDIENST_JOB_SECRET fehlt.",
);