LeaveFlow: Betrieb und Cron-Jobs
Betrieb von LeaveFlow: Messenger-Worker, geplante Jobs, Konsolenbefehle für Jahresübergang und Eskalation, Mailversand und Warteschlange.
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.yamlstartet 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/leaveflowin 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.