Markus Michalski FAQ

LeaveFlow: Betrieb und Cron-Jobs

Betrieb von LeaveFlow: Messenger-Worker, geplante Jobs, Konsolenbefehle für Jahresübergang und Eskalation, Mailversand und Warteschlange.

English Version

Zurück zur Übersicht

LeaveFlow: Betrieb und Cron-Jobs

Ohne Worker passiert nichts Zeitgesteuertes

LeaveFlow führt geplante Aufgaben über den Symfony Scheduler aus. Der Scheduler tickt nur, solange ein Messenger-Worker läuft. Ohne Worker entstehen keine Frist-Warnungen, keine Eskalationen, keine Krankheits-Alarme, keine automatische Deaktivierung nach Austritt und kein automatischer Jahresübergang.

Der Stack aus compose.yaml startet keinen Worker. Richte ihn selbst ein, sonst laufen die geplanten Jobs nie.

graph TD
    A["Cron oder systemd-Timer"] --> B["messenger:consume scheduler_notifications"]
    A --> C["messenger:consume scheduler_maintenance"]
    B --> D["Resturlaub-Verfall-Warnung, Genehmigungs-Eskalation, Krankheits-Alarm"]
    C --> E["Jahresübergang, Austritt-Deaktivierung"]

Geplante Jobs

Job-Name Zeitplan Transport Wirkung
year-transition 0 1 1 1 * (1. Januar, 01:00) scheduler_maintenance Legt aus dem Rest des regulären Urlaubs des Vorjahres Resturlaub-Einträge mit Ablauf 31. März an
exit-deactivation-check 0 7 * * * (täglich 07:00) scheduler_maintenance Deaktiviert Benutzerkonten von Mitarbeitenden, deren Austrittsdatum erreicht ist
entitlement-expiry-check 0 3 * * * (täglich 03:00) scheduler_notifications Benachrichtigt Besitzer von Resturlaub, der in den nächsten 30 Tagen verfällt
approval-escalation-check 0 * * * * (stündlich) scheduler_notifications Benachrichtigt alle aktiven Admins über offene Anträge, die länger als die Eskalations-Schwelle warten
illness-alert-check 0 6 * * * (täglich 06:00) scheduler_notifications Meldet 42 zusammenhängende Kalendertage Krankheit an Teamleitung, Vertretung oder Admins

Die Uhrzeiten sind in der Anwendung festgelegt. Das mitgelieferte PHP-Image setzt date.timezone = Europe/Berlin.

Jobs in der Oberfläche verwalten

Unter Admin → System → Cron-Jobs (/admin/scheduled-jobs) siehst du pro Job Frequenz, Status (Erfolgreich, Fehler, Übersprungen) und den letzten Lauf. Dort kannst du einzelne Jobs aktivieren und deaktivieren. Ein deaktivierter Job läuft als „Übersprungen“. Die Trigger-Zeiten selbst sind nicht einstellbar.

Jobs auf der Konsole verwalten

docker compose exec -u app app php bin/console app:scheduled-job:toggle list
docker compose exec -u app app php bin/console app:scheduled-job:toggle off year-transition
docker compose exec -u app app php bin/console app:scheduled-job:toggle on year-transition

Worker einrichten

Es gibt zwei Transporte, damit eine verstopfte Benachrichtigungs-Warteschlange die Jahresarbeiten nicht aufhält. Beide Worker müssen laufen. Verpasste Ticks während eines Ausfalls holt der Scheduler nicht nach.

Variante mit Cron: Jede Minute startet ein Worker, der sich nach 60 Sekunden beendet.

* * * * * cd /var/www/leaveflow && php bin/console messenger:consume scheduler_notifications --time-limit=60 --memory-limit=128M --quiet
* * * * * cd /var/www/leaveflow && php bin/console messenger:consume scheduler_maintenance --time-limit=60 --memory-limit=128M --quiet

Das Repository bringt Beispiele mit: docs/examples/crontab.example sowie je ein .service und .timer pro Transport unter docs/examples/systemd/. Mit systemd und Persistent=true holt der Timer verpasste Minuten-Ticks nach einem Neustart des Hosts nach.

Läuft die Instanz in Docker, startest du die Worker mit docker compose exec -u app app php bin/console messenger:consume ... (zum Beispiel in einem eigenen Container oder per Cron auf dem Host). Pfade wie /var/www/leaveflow in den Beispielen gelten für eine Installation ohne Docker.

Jobs von Hand ausführen

Befehl Wirkung
php bin/console app:entitlement:year-transition --year=2026 Jahresübergang; --year ist das Quelljahr (Standard: Vorjahr), im Januar 2027 also --year=2026
php bin/console app:entitlement:year-transition --year=2026 --dry-run Zeigt nur den Bericht, ohne etwas zu speichern
php bin/console app:notifications:check-entitlement-expiry Führt die Resturlaub-Verfall-Warnung sofort aus
php bin/console app:notifications:check-approval-escalation Führt die Genehmigungs-Eskalation sofort aus

Der Jahresübergang legt pro Mitarbeiter einen Resturlaub-Eintrag für das Folgejahr an, nur wenn vom regulären Urlaub des Quelljahres Stunden übrig sind, der Mitarbeiter nicht vor dem Zieljahr ausgetreten ist und noch kein Resturlaub-Eintrag für das Zieljahr existiert. Der Ablauf ist der 31. März des Zieljahres. Der Befehl lässt sich gefahrlos wiederholen.

Mailversand und Warteschlange

Umgebung Verhalten
APP_ENV=dev (Compose-Stack) E-Mails werden sofort synchron versendet, im Stack an Mailpit
andere Umgebungen E-Mails und Chat-Nachrichten laufen über den Transport async und brauchen einen Worker: php bin/console messenger:consume async

Fehlgeschlagene Nachrichten landen nach drei Wiederholungen im Transport failed. Die Warteschlange liegt standardmäßig in der Datenbank (doctrine://default).

Der Absender aller System-E-Mails ist fest als no-reply@leaveflow.test (Name „LeaveFlow“) im Code hinterlegt und nicht konfigurierbar. Prüfe, ob dein SMTP-Server diesen Absender akzeptiert.

Logs und Datenbank

Symfony schreibt nach var/log/<umgebung>.log. Der Webserver loggt auf die Standardausgabe des Containers, ohne Header. Ein Backup-Mechanismus gehört nicht zu LeaveFlow: Sichere die MariaDB-Datenbank (im Stack das Volume database_data) und das Verzeichnis public/uploads/ mit dem Firmenlogo.