Laravel 13.31 ajoute des jobs interruptibles, permettant aux workers de file d'attente de capturer le signal SIGTERM envoyé lors des déploiements et de s'arrêter proprement au lieu d'interrompre une tâche à mi-chemin. Les équipes qui exécutent des jobs de longue durée — traitement de dizaines de milliers de lignes, envoi d'e-mails en masse ou génération de rapports — en bénéficient car les données restent cohérentes lors du déploiement d'une nouvelle version.

Pourquoi les déploiements ont tué les jobs

Lorsqu'une nouvelle version arrive, les gestionnaires de processus tels que Supervisor, Docker et Kubernetes demandent aux workers existants de s'arrêter en envoyant un SIGTERM, une requête polie de terminaison. La plupart des workers attendent que le job actuel soit terminé avant de quitter. Le problème survient lorsque le gestionnaire n'accorde que quelques secondes pour s'exécuter. Si un job nécessite plusieurs minutes, le gestionnaire passe au SIGKILL, tuant le processus instantanément. Le job n'atteint jamais un état cohérent, laissant des enregistrements partiellement mis à jour, des fichiers orphelins ou des doublons de travail.

La réponse de Laravel : l'interruption coopérative

Laravel 13.31 introduit un contrat nommé Interruptible qu'une classe de job peut implémenter pour devenir consciente de la requête de terminaison. Lorsque le SIGTERM arrive, Laravel appelle la méthode interrupted() du job. Le framework ne stoppe pas le job automatiquement ; le job doit vérifier un flag que Laravel définit et quitter par lui-même. Ce modèle coopératif permet aux développeurs de terminer l'itération de boucle actuelle, d'annuler les modifications partielles ou d'écrire un point de contrôle avant de quitter.

Comment rendre un job interruptible

  1. Implémenter le contrat – ajoutez implements Interruptible à la définition de la classe du job.
  2. Vérifier le flag à l'intérieur de la boucle de travail – insérez une vérification à chaque itération pour voir si le job doit s'arrêter.
  3. Effectuer le nettoyage – dans interrupted(), persistez tout état qui permettra au job de reprendre plus tard, ou journalisez l'interruption pour une analyse ultérieure.

Le plus grand piège : n'utilisez pas --once

L'exécution du worker de file d'attente avec php artisan queue:work --once désactive entièrement la gestion des signaux. Le worker traite un seul job et s'arrête, mais il n'enregistre jamais le gestionnaire SIGTERM. Par conséquent, tout job interruptible ignore la requête de terminaison et est tué en plein milieu du processus. Ce schéma se retrouve dans les conteneurs pilotés par cron et les déploiements "one-shot". Corrigez cela en utilisant le mode daemon (php artisan queue:work) chaque fois que vous avez besoin de jobs interruptibles.

Surveiller les interruptions

Laravel déclenche deux événements auxquels vous pouvez vous greffer :

  • WorkerInterrupted – émis chaque fois qu'un worker reçoit un SIGTERM. Journaliser cet événement donne une vue d'ensemble de la fréquence à laquelle les déploiements interrompent les workers.
  • JobInterrupted – émis uniquement si le job actuel implémente le contrat Interruptible. Utilisez cet événement pour déclencher un nettoyage spécifique au job, comme la suppression de fichiers temporaires ou la mise à jour d'un marqueur de "dernière ligne traitée".

L'écoute de ces événements permet aux équipes de construire des tableaux de bord montrant l'impact des déploiements et de repérer les jobs qui sont fréquemment interrompus.

Amélioration du rapport de taille de la file

La version ajoute une méthode totalSize() au gestionnaire de file d'attente, renvoyant le nombre total de jobs en attente dans toutes les files. La valeur est fiable pour les pilotes basés sur une base de données et Redis, qui rapportent des comptes réels. Les pilotes comme SQS, Sync et Beanstalkd renvoient toujours zéro car ils n'exposent pas de décompte via l'API de Laravel. Les équipes utilisant SQS doivent continuer à s'appuyer sur les métriques CloudWatch pour la profondeur de la file.

Ce que cela signifie pour différentes configurations

  • Docker/Kubernetes – la période d'arrêt progressif peut désormais être utilisée efficacement. Étendez le délai de grâce de terminaison pour que les jobs aient quelques secondes pour détecter le flag et quitter proprement.
  • Supervisor – réglez stopwaitsecs à une valeur supérieure au temps que vous prévoyez pour la fin d'un job après la réception du flag d'interruption.
  • Jobs hérités (Legacy) – examinez tout job qui s'exécute plus longtemps que le timeout du gestionnaire et, si possible, rendez-le interruptible.

Contre-argument : complexité ajoutée

Cette fonctionnalité ne remplace pas une configuration appropriée des timeouts. Si la boucle d'un job ne vérifie jamais le flag d'interruption, le gestionnaire enverra toujours un SIGKILL. Les équipes doivent auditer les chemins de code de longue durée et insérer des vérifications à des points de rupture logiques. Certains développeurs pourraient trouver le boilerplate supplémentaire — implémenter un contrat et ajouter des vérifications de flag — peu attrayant pour des jobs courts qui se terminent déjà dans la fenêtre d'arrêt.

Liste de contrôle d'actions

  1. Recherchez le flag --once dans les scripts de déploiement et remplacez-le par le mode daemon lorsque des jobs interruptibles sont utilisés.
  2. Identifiez les jobs les plus longs (ceux qui traitent des dizaines de milliers de lignes ou s'exécutent pendant plusieurs minutes) et ajoutez le contrat Interruptible.
  3. Insérez une vérification de flag à l'intérieur de chaque itération de boucle, et déplacez tout code de finalisation nécessaire dans la méthode interrupted().
  4. Connectez des écouteurs à WorkerInterrupted et JobInterrupted pour collecter des métriques sur la fréquence à laquelle les déploiements affectent le traitement.
  5. Pour les files d'attente Redis ou de base de données, utilisez totalSize() pour surveiller le backlog ; pour SQS, maintenez les alarmes CloudWatch en place.

Considérez les arrêts déclenchés par le déploiement comme une étape coordonnée plutôt que comme une interruption brutale. Laravel 13.31 garantit la cohérence des données et réduit les maux de tête opérationnels liés aux jobs à moitié terminés. Le compromis est une légère augmentation de la responsabilité du code, mais les équipes qui s'appuient sur un traitement en arrière-plan intensif bénéficient d'un environnement de production plus fiable.