feat: complete notdienst planning, quick wins and notifications
This commit is contained in:
@@ -59,4 +59,11 @@ UNION ALL
|
||||
SELECT 'notdienst_alerts.educatorId' AS relation, count(*) AS invalid_rows FROM "notdienst_alerts" c JOIN "educators" p ON c."educatorId" = p.id WHERE c."kitaId" IS DISTINCT FROM p."kitaId"
|
||||
UNION ALL
|
||||
SELECT 'announcement_reads.userId' AS relation, count(*) AS invalid_rows FROM announcement_reads r JOIN announcements a ON r."announcementId" = a.id JOIN users u ON r."userId" = u.id WHERE u."kitaId" IS DISTINCT FROM a."kitaId"
|
||||
|
||||
UNION ALL
|
||||
SELECT 'notdienst_emails.familyId' AS relation, count(*) AS invalid_rows FROM "notdienst_emails" c JOIN "families" p ON c."familyId" = p.id WHERE c."kitaId" IS DISTINCT FROM p."kitaId"
|
||||
UNION ALL
|
||||
SELECT 'notdienst_emails.userId' AS relation, count(*) AS invalid_rows FROM "notdienst_emails" c JOIN "users" p ON c."userId" = p.id WHERE c."kitaId" IS DISTINCT FROM p."kitaId"
|
||||
UNION ALL
|
||||
SELECT 'notdienst_emails.planId' AS relation, count(*) AS invalid_rows FROM "notdienst_emails" c JOIN "notdienst_plans" p ON c."planId" = p.id WHERE c."kitaId" IS DISTINCT FROM p."kitaId"
|
||||
) violations WHERE invalid_rows > 0;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
const secret = process.env.NOTDIENST_JOB_SECRET;
|
||||
if (!secret || secret.length < 32) {
|
||||
console.error(
|
||||
"Notdienst-Fristprüfung deaktiviert: NOTDIENST_JOB_SECRET muss mindestens 32 Zeichen haben.",
|
||||
"Notdienst-Hintergrundjob deaktiviert: NOTDIENST_JOB_SECRET muss mindestens 32 Zeichen haben.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -23,11 +23,11 @@ async function tick() {
|
||||
);
|
||||
if (!response.ok)
|
||||
console.error(
|
||||
`Notdienst-Fristprüfung: HTTP ${response.status}; erneuter Versuch in einer Minute.`,
|
||||
`Notdienst-Hintergrundjob: HTTP ${response.status}; erneuter Versuch in einer Minute.`,
|
||||
);
|
||||
} catch {
|
||||
console.error(
|
||||
"Notdienst-Fristprüfung momentan nicht erreichbar; erneuter Versuch in einer Minute.",
|
||||
"Notdienst-Hintergrundjob momentan nicht erreichbar; erneuter Versuch in einer Minute.",
|
||||
);
|
||||
}
|
||||
if (!stopped)
|
||||
|
||||
@@ -6,3 +6,5 @@ cpSync('scripts/start-production.sh', '.next/standalone/scripts/start-production
|
||||
cpSync('scripts/notdienst-alarm-worker.mjs', '.next/standalone/scripts/notdienst-alarm-worker.mjs');
|
||||
cpSync('scripts/runtime-database-url.mjs', '.next/standalone/scripts/runtime-database-url.mjs');
|
||||
cpSync('scripts/verify-runtime-isolation.mjs', '.next/standalone/scripts/verify-runtime-isolation.mjs');
|
||||
|
||||
cpSync('scripts/start-runtime.mjs', '.next/standalone/scripts/start-runtime.mjs');
|
||||
|
||||
@@ -7,7 +7,4 @@ if [ -n "${APP_DATABASE_PASSWORD_FILE:-}" ]; then
|
||||
fi
|
||||
unset POSTGRES_PASSWORD PGADMIN_DEFAULT_PASSWORD APP_DATABASE_PASSWORD MIGRATION_DATABASE_URL
|
||||
# Schema changes are applied by the maintenance image before runtime startup.
|
||||
if [ -n "${NOTDIENST_JOB_SECRET:-}" ]; then
|
||||
node scripts/notdienst-alarm-worker.mjs &
|
||||
fi
|
||||
exec node server.js
|
||||
exec node scripts/start-runtime.mjs
|
||||
|
||||
@@ -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.",
|
||||
);
|
||||
Reference in New Issue
Block a user