veilletech.fr
13 nov. Feed du jour
#05 SYMFONY Article

Symfony 8.2 : Messenger chaîne et compense ses messages

Le flux se lit à l'envoi, plus dans dix handlers.

Symfony 8.2 ajoute à Messenger des stamps qui déclarent un flux de messages dès le premier envoi : ChainStamp pour l'enchaînement, DispatchOnFailureStamp pour la compensation, des identifiants de causalité et de corrélation pour le suivi. Le transport sync:// gagne aussi les tentatives et le failure transport, jusqu'ici ignorés sans avertissement.

3 min de lectureintermédiairevidéo 1:20
Partager
Sommaire4 sections
  1. Ce qui se passe
  2. Les nouveautés
  3. Comment s'y prendre
  4. À retenir

Ce qui se passe

Un processus métier tient souvent en plusieurs messages : débiter la carte, expédier la commande, l'annuler si une étape échoue. Dans Messenger, on le construisait jusqu'ici en faisant envoyer l'étape suivante par chaque handler : la séquence était dispersée, et chaque handler couplé à celui d'après. Symfony 8.2 ajoute des stamps qui déclarent le flux au moment d'envoyer le premier message. L'idée vient d'un comparatif entre Messenger et Ecotone.

Les nouveautés

Enchaîner — ChainStamp. Il porte la liste des étapes. Un message n'est envoyé qu'une fois le précédent traité par tous ses handlers. Les étapes restantes voyagent dans le stamp : une étape relancée reprend la chaîne là où elle s'était arrêtée. Une étape sans routage propre part sur le transport d'où venait la précédente, ce qui permet de relancer chaque étape séparément. Si une étape échoue, la chaîne s'arrête.

Compenser — DispatchOnFailureStamp. Il désigne le message à envoyer quand celui qui le porte échoue définitivement : après toutes ses tentatives dans un worker, ou à l'exception en envoi synchrone. Dans une chaîne, chaque étape transmet le stamp à la suivante, si bien que la compensation (CancelOrder dans l'exemple du billet) part une seule fois, quelle que soit l'étape qui casse. Le failure transport ne reçoit plus le message en échec que si la compensation ne peut pas être envoyée.

Suivre — l'option identity_stamps. Chaque message reçoit un MessageIdStamp, stable à travers tentatives et rejeux. Un message envoyé par un handler reçoit un CausationStamp avec l'identifiant du message en cours, et tout le flux partage un CorrelationStamp. Les identifiants font 32 caractères aléatoires. L'option est désactivée par défaut parce qu'elle modifie les enveloppes sérialisées ; l'inbox Messenger, autre nouveauté de 8.2, en a besoin.

Propager le contexte — PropagatedStampInterface. Un stamp qui l'implémente (identifiant de locataire, de trace) est recopié sur chaque message envoyé pendant le traitement de celui qui le porte : plus besoin d'en faire une propriété de chaque message. Les handlers peuvent aussi recevoir des stamps, ou l'Envelope entière, en arguments après le message — pratique pour mettre l'identifiant de corrélation dans les logs.

sync:// gagne retry et failure_transport. Jusqu'ici, retry_strategy et failure_transport étaient ignorés en silence pour un message traité en synchrone, un webhook de paiement par exemple. En 8.2, les deux nouvelles options du transport sync:// les activent : les tentatives sont immédiates, sans les délais de la stratégie, puis le message part dans le failure transport au lieu de lever une exception. On le retrouve avec messenger:failed:show et messenger:failed:retry.

Tâches planifiées. #[AsCronTask] et #[AsPeriodicTask] acceptent une option stamps : une liste de classes, ou une correspondance classe → arguments du constructeur. Les stamps d'envoi comme DelayStamp ne s'appliquent que si la tâche passe par un transport (options transports ou use_messenger_routing).

Comment s'y prendre

  1. Cherchez les handlers qui envoient eux-mêmes l'étape suivante : ce sont les candidats à une chaîne.
  2. Commencez par un flux qui a une compensation : c'est là que DispatchOnFailureStamp retire le plus de code.
  3. Si vous pensiez qu'un retry_strategy protégeait vos messages en sync://, il ne servait à rien : configurez les nouvelles options du transport.
  4. Activez identity_stamps en sachant que le format des enveloppes en file change.

Source : Symfony Blog, en anglais.