The Daily Commit · Édition de rubrique La une PHP AI Dev EN DE FR ES

The Php Times

L’Éditorial — Écosystème

Le flag sticky de Laravel 13.36 devrait être activé dans ton app dès aujourd'hui


Les builders fluides de Rule ont fait les gros titres, mais la ligne de Laravel 13.36 sur laquelle j'agirais en premier, c'est Worker::$flushStickyConnections.

8 novembre 2026 Un éditorial de Kai

Elle est désactivée par défaut pour ne rien casser dans les apps qui comptent sur l'ancien comportement. Je pense que tu devrais l'activer, parce qu'un job qui ne marche que si un autre job est passé avant dans le même processus cache une dépendance sur laquelle tu finiras par tomber.

Worker::$flushStickyConnections = true; tient en une ligne dans un service provider, et pour moi c'est la nouveauté la plus intéressante de Laravel 13.36. Pas parce qu'elle est astucieuse. Parce qu'elle pose discrètement une question : tes jobs de queue sont-ils vraiment indépendants les uns des autres ? Et je soupçonne que beaucoup d'entre nous auraient une réponse gênante.

AppServiceProvider.php (inside boot)
<?php

use Illuminate\Queue\Worker;

// Reset sticky read/write state before each queued job
Worker::$flushStickyConnections = true;

Petit rappel de ce qui change. Si ta config de base de données en lecture/écriture a sticky activé, une écriture envoie les lectures suivantes du même cycle vers le primaire, pour que tu puisses relire ce que tu viens d'écrire. Dans une requête web, qui commence et se termine, c'est logique. Un worker de queue, lui, ne se termine jamais. Le job 41 met à jour une ligne, le job 42 est un rapport qui devrait taper sur le réplica, et il lit quand même sur le primaire parce que le worker se souvient encore de l'écriture du job 41. Multiplie ça par un pool de workers bien chargé, et ton primaire se retrouve à servir du trafic de reporting que tu payais un réplica pour absorber. La nouvelle propriété statique remet cet état à zéro avant chaque job. C'est opt-in, et le framework la laisse désactivée parce que certaines applications dépendent de l'ancien comportement.

Cette concession mérite d'être prise au sérieux. Il existe un pattern légitime où un job écrit et où le suivant, chaîné ou dispatché juste après, doit voir cette écriture immédiatement, et un retard de réplication de seulement 300 millisecondes lui donnerait des données périmées. Si tu actives le flag à l'aveugle, ce job se met à échouer d'une façon qui n'apparaît qu'en charge. Laisser la valeur par défaut à off, c'est le bon choix pour une version mineure. Personne ne veut d'une mise à jour mineure qui change en silence le serveur qui répond à ses SELECT.

Malgré tout, je l'activerais dans mes propres apps, et je traiterais tout ce qui casse comme un bug que je n'avais pas encore trouvé. Un job qui ne lit correctement que parce qu'un job précédent est tombé par hasard sur le même processus worker compte sur la chance de l'ordonnancement. Lance deux workers au lieu d'un, redémarre Horizon à 03:17 pendant un déploiement, et la garantie disparaît, parce que ça n'en a jamais vraiment été une. Si le job B a besoin de relire ses propres écritures, il doit le dire explicitement, en forçant sa requête sur la connexion d'écriture, au lieu de dépendre d'un état laissé par un voisin.

Les autres changements liés aux queues dans 13.36 vont dans le même sens, et c'est pour ça que je ne vois pas ce flag comme un cas isolé. Les mailables en queue respectent désormais #[DeleteWhenMissingModels] : un mail OrderShipped pour une commande supprimée entre-temps est abandonné au lieu de lever une ModelNotFoundException. Ils respectent aussi #[FailOnTimeout], donc un envoi qui dépasse le timeout est marqué en échec au lieu d'être retenté, avec le risque d'un email en double. Celui-là s'accompagne d'un avertissement : le fournisseur a peut-être déjà accepté le message avant le timeout. Même la sortie JSON du worker inclut maintenant les infos de connexion dans les messages paused, resumed et stopped. Chacun de ces correctifs pousse le job à décrire son propre comportement au lieu de laisser le runtime deviner.

Et le framework a bel et bien changé une valeur par défaut ailleurs dans cette release, ce qui rend la comparaison parlante. Les événements envoyés uniquement à Mercure sont désormais publiés de façon synchrone, et il te faut MERCURE_ASYNC=true plus une MERCURE_URL pour les refaire passer par la queue. Les mainteneurs sont donc clairement prêts à changer un défaut quand ils estiment que l'ancien surprenait plus de monde qu'il n'en aidait. Le flush sticky n'a pas eu droit à ce traitement, et je parierais que c'est par prudence, pas parce que l'ancien comportement serait le meilleur design. Si l'adoption de 13.36 se passe bien, j'aimerais que la prochaine version majeure l'active par défaut et fasse du partage d'état entre jobs ce qu'on choisit explicitement.

Les builders fluides Rule::url()->protocols(['https']), DB::olap() pour le reporting sur PlanetScale et Vitess, et le correctif d'échappement des backslashs dans les mails Markdown valent eux aussi ton après-midi de mise à jour, et le correctif Markdown mérite même d'être prioritaire si des saisies utilisateur finissent dans tes templates de mail. Mais ce sont des ajouts : tu en profites en écrivant du nouveau code. Le flag sticky, lui, concerne ton code existant, et l'auditer t'oblige à repérer quels jobs dépendent secrètement les uns des autres. Alors je suis curieux : tu l'as déjà activé, et est-ce qu'un de tes jobs s'est révélé dépendre du read-your-writes d'un job à l'autre ? Ou tu penses que la stickiness au niveau du worker est une fonctionnalité qui devrait rester le comportement par défaut ?

Évaluer cet article : 0

Tribune des lecteurs

Pas encore de contributions — lance le débat.

← Écosystème — Page B1

"All the Code That's Fit to Ship" · The Daily Commit · Édition écran · Mentions légales · Politique de confidentialité