Scheduler
Der Scheduler ermöglicht, Tasks oder Commands automatisiert in bestimmten Intervallen auszuführen. Hierfür wird pro Projekt lediglich ein einziger Cronjob auf dem Server benötigt, der minütlich den Scheduler aufruft, welcher daraufhin die auszuführenden Tasks und Commands ermittelt.
Die Intervalle werden also nicht in der crontab
-Datei, sondern im Code festgelegt. Das hat den Vorteil, dass diese Informationen in der Versionsverwaltung gespeichert sind und das Projekt leichter auf einen anderen Server umgezogen werden kann.
Vorbereitung
Um den Scheduler zu aktivieren, muss folgender Eintrag in der crontab
-Datei ergänzt werden. Dabei wird der absolute Pfad zur cmd
-Datei des Projekts eingetragen.
* * * * * php /srv/www/.../project/cmd scheduler:run
Intervalle definieren
Welche Tasks und Commands durch den Scheduler ausgeführt werden sollen, wird in der Methode initScheduler
der Klasse App\Boot\App
definiert.
public static function initScheduler(): void
{
Scheduler::add(new ExampleTask())->daily()->at(3);
}
Mit der Methode Scheduler::add(Task|Command $task)
wird dem Scheduler ein neuer Task oder Command hinzugefügt. Die Methode gibt eine Instanz der Klasse Schedule
zurück, die über viele Methoden verfügt, um diverse Intervalle zu definieren.
Allgemeine Intervalle
Üblicherweise wird zunächst eine dieser Methoden verwendet, um ein allgemeines Intervall festzulegen. Dieses kann mit den Methoden der nachfolgenden Abschnitte konkretisiert und eingeschränkt werden.
Methode | Beschreibung | entspricht Cron |
---|---|---|
everyMinute() | minütlich | * * * * * |
everyMinutes(int $x) | alle $x Minuten | */$x * * * * |
everyHour() | stündlich (zur vollen Stunde) | 0 * * * * |
everyHours(int $x) | alle $x Stunden | 0 */$x * * * |
daily() | täglich um 00:00 | 0 0 * * * |
weekly() | wöchentlich montags um 00:00 | 0 0 * * 1 |
monthly() | monatlich am 01. um 00:00 | 0 0 1 * * |
yearly() | jährlich am 01.01. um 00:00 | 0 0 1 1 * |
cron(string $rules) | Cron-Ausdruck | $rules |
Die Methode cron(string $rules)
erwartet einen vollständigen Cron-Ausdruck der Form * * * * *
(Minute, Stunde, Tag des Monats, Monat, Tag der Woche). Sie dient nur dazu, alte Einträge der crontab
-Datei schnell in das Framework kopieren zu können. Durch die anderen Methoden wird der Code lesbarer und verständlicher.
Einzelne Regeln
Mit den folgenden Methoden können einzelne Regeln gesetzt werden, wobei der vorherige Wert der jeweiligen Regel überschrieben wird. Diesen Methoden können Zahlen aus dem gültigen Wertebereich übergeben werden, aber auch Strings in Cron-Syntax, z.B. 15,45
, */5
oder 0-30/5
.
Methode | Beschreibung | Wertebereich |
---|---|---|
setMinute(string $rule) | Minute | 0 - 59 |
setHour(string $rule) | Stunde | 0 - 23 |
setDayOfWeek(string $rule) | Tag der Woche | 0 - 7* |
setDay(string $rule) | Tag des Monats | 1 - 31 |
setMonth(string $rule) | Monat | 1 - 12 |
setYear(string $rule) | Jahr | 0 - 9999 |
*Da es unterschiedliche Ansichten gibt, ob die Woche montags oder sonntags beginnt, werden für den Sonntag die Werte 0 und 7 zugelassen.
Hilfsmethoden
Folgende Methoden erleichtern die Nutzung der Methoden für einzelne Regeln, indem sie bestimmte Regeln kombinieren oder durch konkrete Namen intuitiver machen.
Methode | entspricht |
---|---|
at(string $hour, string $minute = '0') | setHour($hour)->setMinute($minute) |
on(string $month, string $day) | setMonth($month)->setDay($day) |
onMondays() | setDayOfWeek('1') |
onTuesdays() | setDayOfWeek('2') |
onWednesdays() | setDayOfWeek('3') |
onThursdays() | setDayOfWeek('4') |
onFridays() | setDayOfWeek('5') |
onSaturdays() | setDayOfWeek('6') |
onSundays() | setDayOfWeek('7') |
onWeekdays() | setDayOfWeek('1-5') |
onWeekends() | setDayOfWeek('6,7') |
Einschränkungen
Mit diesen Methoden kann die Ausführung eines Tasks oder Commands weiter eingeschränkt werden. Die jeweiligen Bedingungen müssen also zusätzlich zu den zeitlichen Regeln erfüllt sein.
Methode | Beschreibung |
---|---|
between(string $start, string $end) | noch nicht implementiert |
timezone(string $zone) | noch nicht implementiert |
environments(string $envs) | noch nicht implementiert |
if(Closure $cb) | noch nicht implementiert |
Ablaufsteuerung
Methode | Beschreibung |
---|---|
inBackground() | siehe Parallelisierung |
Beispiele
Einige Beispiele sollen die Nutzung der oben beschriebenen Methoden verdeutlichen.
public static function initScheduler(): void
{
// alle 5 Minuten
Scheduler::add(new ExampleTask())->everyMinutes(5);
// stündlich um viertel vor und viertel nach
Scheduler::add(new ExampleTask())->everyHour()->setMinute('15,45');
// alle 3 Stunden um viertel nach
Scheduler::add(new ExampleTask())->everyHours(3)->setMinute(15);
// täglich um 03:30
Scheduler::add(new ExampleTask())->daily()->at(3, 30);
// täglich um 00:15, 00:45, 12:15 und 12:45
Scheduler::add(new ExampleTask())->daily()->at('0,12', '15,45');
// monatlich am 01. und 15. um 06:00
Scheduler::add(new ExampleTask())->monthly()->setDay('1,15')->at(6);
// jährlich am 24.12. um 18:00
Scheduler::add(new ExampleTask())->yearly()->on(12, 24)->at(18);
}
Parallelisierung
Standardmäßig führt der Scheduler alle anstehenden Tasks sequentiell aus, entsprechend der Reihenfolge in der Methode initScheduler
. Falls ein Task ungewöhnlich lange braucht kann es also vorkommen, dass folgende Tasks verzögert oder aufgrund von Zeitüberschreitung gar nicht ausgeführt werden.
Um dieses Problem zu umgehen, kann der Scheduler durch die Methode inBackground
angewiesen werden, Tasks parallel im Hintergrund auszuführen. In diesem Fall ruft der Scheduler den Command task:exec
auf, sodass jeder Hintergrund-Task in einem eigenen PHP-Prozess läuft.
public static function initScheduler(): void
{
Scheduler::add(new ExampleTask())->everyHour()->inBackground();
}