Symfony, Broadway et le replay d'event

Par @jbnahan69
Attention, cet article est ancien. Les informations ou instructions qu'il contient peuvent ne plus fonctionner.

[English version]

L’un des principaux atouts qui reviennent souvent lorsque l’on parle de l’EventSourcing est la réémission des évènements afin de reconstruire la vue (par exemple). Cela peut être pour la construction d’une nouvelle base de vue ou le rafraichissement de la vue désynchronisée.

Ne vous est-il jamais arrivé de vous demander comment s’y prendre pour ne pas renvoyer les emails basés sur les évènements émis par les agrégats ?


Dans mon cas, le dilemme est plutôt important car beaucoup de choses se basent sur les évènements. S’ils sont réémis, tous les traitements sont réexécutés.

Dans mon projet, la librairie utilisée pour l’implémentation de CQRS/ES est Broadway de QandidateLabs.

Pour utiliser le bus d’évènements par défaut pour exécuter les actions liées aux évènements, il faut taguer son service avec « broadway.domain.event_listener » et étendre Broadway\Processor\Processor.
Tous les services seront injectés dans le bus par une «compiler pass» du bundle. Cette dernière prend trois arguments : l’identifiant du service de bus, le tag des services à lui injecter et l’interface que les services doivent implémenter pour être enregistrés.

Il est donc possible de réutiliser ce code pour ajouter un nouveau bus d’évènements.

Pour exécuter uniquement les actions pour la mise à jour de la vue, 3 étapes sont nécessaires :
1) Ajouter un nouveau service de bus d'évènements

service:
     mon_bundle.event_handling.event_bus:
          class: Broadway\EventHandling\SimpleEventBus
          lazy: true

2) Ajouter un nouveau tag à tous les services permettant la mise à jour de la vue. Par exemple `mon_bundle.domain.event_listener`.
3) Exécuter une nouvelle `compiler pass` en lui passant les bons paramètres afin de configurer le nouveau bus au chargement du framework.

use Broadway\Bundle\BroadwayBundle\DependencyInjection\RegisterBusSubscribersCompilerPass;
$container->addCompilerPass(
     new RegisterBusSubscribersCompilerPass(
          'mon_bundle.event_handling.event_bus',
          'mon_bundle.domain.event_listener',
          'Broadway\EventHandling\EventListenerInterface'
     )
);

Tout est réalisable avec un peu de configuration ! Vous n’écrirez pas plus de code. Voilà un code SOLID.

Vos écouteurs d’évènements doivent également l’être. Une responsabilité par écouteur (mise à jour de la vue, envoi de courriel, création de fichiers, etc.) afin de bien séparer le code et le rendre plus testable.

Enfin, lors de la réémission des évènements, il suffit de les émettre sur le bus d'évènements dédié à la relecture pour réaliser uniquement la mise à jour de la vue.

Voilà qui est fait ! Vous pouvez réémettre tous les évènements pour mettre à jour la vue sans devoir changer la configuration de l’application de production pour éviter la réexpédition des courriels.

Retrouver un core source fonctionnel sur mon github.

Vous pouvez maintenant partager vos expériences dans les commentaires.

Author avatar
Jean-Baptiste Nahan

Consultant Expert Web, j'aide les entreprises ayant des difficultés avec leur projet Web (PHP, Symfony, Sylius).

@jbnahan69 | Macintoshplus | Linkedin | JB Dev Labs