import "dotenv/config"; import { getMailConfig } from "../src/server/mail/config"; import { isQueueEnabled } from "../src/server/mail/queue"; import { scheduleDueReminders, shutdownWorkers, startMailWorker, startReminderWorker, } from "../src/server/mail/worker"; /** * SEC1 — Einstiegspunkt des Mail-Workers (`npm run worker:mail`). * * Betriebsmodus: eigener Prozess/Container neben der App (Coolify), damit * Zustellung, Retry und der tägliche Fristen-Job unabhängig vom Web-Request- * Lebenszyklus laufen. Ohne `REDIS_URL` gibt es keinen Worker-Betrieb — die App * versendet dann inline (siehe src/server/mail/queue.ts). */ async function main() { if (!isQueueEnabled()) { console.error( "[mail-worker] REDIS_URL ist nicht gesetzt. Ohne Redis läuft der Versand inline in der App; ein Worker wird nicht benötigt.", ); process.exit(1); } const { config, reason } = getMailConfig(); if (!config) { // Kein harter Abbruch: der Worker läuft weiter und meldet den Zustand — so // ist nach dem Nachreichen der Secrets kein Neustart-Rennen nötig. console.warn(`[mail-worker] ${reason}`); } else { console.info(`[mail-worker] SMTP ${config.host}:${config.port} (secure=${config.secure})`); } const mailWorker = startMailWorker(); const reminderWorker = startReminderWorker(); await scheduleDueReminders(); console.info("[mail-worker] bereit — Queue 'mail' + Fristen-Job (täglich 07:00 Europe/Berlin)."); let shuttingDown = false; const stop = async (signal: string) => { if (shuttingDown) return; shuttingDown = true; console.info(`[mail-worker] ${signal} — fahre herunter…`); await shutdownWorkers([mailWorker, reminderWorker]); process.exit(0); }; process.on("SIGTERM", () => void stop("SIGTERM")); process.on("SIGINT", () => void stop("SIGINT")); } main().catch((err) => { console.error("[mail-worker] Start fehlgeschlagen:", err); process.exit(1); });