Paquet Laravel : le planificateur de tâches
Le paquet Laravel de SilenceWatch surveille vos tâches planifiées sans que vous déclariez quoi que ce soit : il lit la planification, déclare chaque tâche avec sa vraie expression cron, et envoie un signal autour de chaque exécution. Il est sous licence Apache 2.0, volontairement, pour pouvoir être embarqué dans n’importe quelle application.
Laravel 12 et 13, PHP 8.2 ou plus récent. Aucune autre dépendance.
Mise en route
Section intitulée « Mise en route »composer require silencewatch/laravelCréez la clé d’API dans Réglages › Clés d’API de votre projet et donnez-la à l’application :
SILENCEWATCH_API_KEY=sw_...# SILENCEWATCH_URL=https://watch.example.com # seulement si vous hébergez SilenceWatch vous-mêmeC’est tout : le service provider est découvert par Laravel, et rien ne change dans votre planification.
Ce qu’il fait
Section intitulée « Ce qu’il fait »Le paquet écoute les événements que le planificateur de Laravel émet déjà (ScheduledTaskStarting, ScheduledTaskFinished, ScheduledTaskFailed, ScheduledBackgroundTaskFinished). Vos tâches ne sont ni enveloppées ni modifiées.
Déclaration. La première fois que schedule:run exécute une tâche, toute la planification est déclarée à POST /api/v1/checks/sync en une seule requête, et les clés de ping renvoyées sont gardées dans le cache. Les exécutions suivantes les réutilisent : la déclaration n’est renvoyée que si la planification a changé (un déploiement), ou une fois par jour. php artisan silencewatch:sync la déclare tout de suite, ce qui convient à la fin d’un script de déploiement, et liste ce qui n’est pas surveillé et pourquoi.
Signaux. Autour de chaque exécution :
POST /p/<clé>/start au démarrage de la tâchePOST /p/<clé>/<code de sortie>?duration_ms= à sa fin (0 réussit, tout autre code échoue)POST /p/<clé>/fail?duration_ms= si elle lève une exceptionUne tâche en arrière-plan (->runInBackground()) signale sa fin depuis le processus schedule:finish que Laravel lance à sa sortie, avec son code de sortie.
Chaque tâche reçoit une identité stable qui la relie à son historique d’un déploiement et d’un serveur à l’autre :
| Planifiée avec | Clé |
|---|---|
Schedule::command('backup:run --only-db') |
artisan:backup:run --only-db |
Schedule::exec('/opt/scripts/export.sh') |
exec:/opt/scripts/export.sh |
Schedule::job(new PruneOrders) |
call:App\Jobs\PruneOrders |
Schedule::call(...)->name('refresh-rates') |
call:refresh-rates |
Le nom affiché dans SilenceWatch est le ->description() de la tâche quand elle en a un. Une tâche qui disparaît de la planification est marquée orpheline, jamais supprimée.
Configuration
Section intitulée « Configuration »Des variables d’environnement. Publiez le fichier de configuration avec php artisan vendor:publish --tag=silencewatch-config seulement si vous devez calculer une valeur en PHP.
| Variable | Défaut | |
|---|---|---|
SILENCEWATCH_API_KEY |
aucun | Sans clé, rien n’est envoyé |
SILENCEWATCH_URL |
https://app.silencewatch.com |
Votre propre instance si vous hébergez |
SILENCEWATCH_ENVIRONMENT |
APP_ENV |
Fait partie de l’identité d’un check |
SILENCEWATCH_ENABLED |
true |
false supprime tout |
SILENCEWATCH_DEFAULT_GRACE |
300 |
Secondes de retard tolérées avant une alerte |
SILENCEWATCH_REPORT_START |
true |
false pour n’envoyer que le résultat |
SILENCEWATCH_TIMEOUT |
2 |
Secondes par requête |
SILENCEWATCH_PRUNE |
true |
false quand plusieurs applications partagent un projet et un environnement |
SILENCEWATCH_CACHE_STORE |
le magasin par défaut | Où les clés de ping sont gardées entre deux exécutions |
SILENCEWATCH_PER_INSTANCE_TASKS |
aucun | Tâches surveillées sur chaque serveur, voir plus bas |
SILENCEWATCH_INSTANCE_ID |
aucun | Le nom stable du serveur, pour ces tâches |
Les tâches limitées à certains environnements (->environments('production')) ne sont déclarées que depuis ceux-ci. Les fuseaux horaires sont ceux de la tâche (->timezone()), sinon app.schedule_timezone, sinon app.timezone.
Plusieurs serveurs
Section intitulée « Plusieurs serveurs »Quand le planificateur tourne sur plusieurs serveurs, tous déclarent les mêmes tâches dans le même environnement : chaque tâche est donc un seul check pour tous, en bonne santé tant que l’un d’eux la signale.
- Une tâche avec
->onOneServer()tourne sur un serveur à la fois, et le check l’entend quel qu’il soit. C’est la bonne règle. - Une tâche sans elle tourne sur chaque serveur. Le check reste en bonne santé tant que l’un
d’eux l’exécute : un serveur dont le planificateur est bloqué (son entrée cron disparue, par
exemple) passe inaperçu pendant qu’un autre travaille. Si la tâche doit tourner une seule fois,
ajoutez
->onOneServer(); si elle doit tourner partout, lisez la suite.
Les tâches qui doivent tourner sur chaque serveur (vider un cache local, supprimer des fichiers temporaires) peuvent être surveillées sur chacun :
SILENCEWATCH_PER_INSTANCE_TASKS=artisan:cache:prune-local,exec:*SILENCEWATCH_INSTANCE_ID=web-1Ces tâches sont déclarées dans un environnement propre au serveur, production.web-1 : chaque
serveur a son check, et celui qui se tait est vu pendant que les autres signalent. Un * final
désigne un préfixe ; les autres tâches restent partagées. Une tâche avec ->onOneServer() n’est
jamais surveillée par serveur, puisqu’un seul serveur exécute chaque exécution : le paquet le
signale et la garde partagée. Les clés de ping sont mises en cache par serveur, si bien que des
serveurs qui partagent un cache ne redéclarent pas à chaque exécution.
SILENCEWATCH_INSTANCE_ID n’a pas de valeur par défaut, et doit rester le même d’un redémarrage
et d’un déploiement à l’autre (le nom d’hôte d’un serveur) : un nom qui change laisserait des
checks que plus rien ne signale, et qui tomberaient en panne. Sans lui, les tâches listées sont
surveillées comme partagées, avec un avertissement. Quand vous retirez un serveur pour de bon,
supprimez ses checks.
Règles qu’il ne transgresse pas
Section intitulée « Règles qu’il ne transgresse pas »- Il ne fait jamais échouer votre tâche. Toute erreur est interceptée ; une tâche réussie n’est jamais signalée à Laravel comme échouée à cause du paquet.
- Il coûte presque rien à vos tâches. PHP n’a pas de fil d’arrière-plan, donc un signal est une requête que le planificateur attend, au plus
SILENCEWATCH_TIMEOUT. Dès que SilenceWatch n’a pas répondu, les autres tâches de cette exécution ne l’attendent plus. - Il se dégrade en silence. Sans clé, sans réseau, sans serveur : la planification tourne exactement comme sans le paquet, et l’exécution suivante réessaie.
- Aucune dépendance en dehors de Laravel.
Non surveillé
Section intitulée « Non surveillé »Laissé hors de la déclaration, et listé par php artisan silencewatch:sync :
- Une closure sans nom n’a pas d’identité stable. Donnez-lui
->name('...'). - Une tâche avec une condition (
->between(),->unlessBetween(),->when(),->skip()) : son expression cron dit quand elle peut s’exécuter, pas quand elle le fait, et la surveiller déclencherait de fausses alertes. Créez son check à la main et pingez-le vous-même avec l’API de ping. - Les expressions cron « jour ouvré le plus proche » (
15W), que le serveur ne sait pas évaluer.
Une tâche planifiée deux fois est déclarée depuis la planification qui se déclenche le plus souvent. Un job en file d’attente (Schedule::job()) est signalé quand il est envoyé dans la file, pas quand un worker l’exécute.