Je travaille sur un petit exemple d'application pour apprendre les concepts du CQRS et du sourcing d'événements. J'ai un Basket
agrégat et un Product
agrégat qui devraient fonctionner indépendamment.
Voici un pseudo code pour montrer l'implémentation
Basket { BasketId; OrderLines; Address; }
// basket events
BasketCreated { BasketId; }
ItemAdded { BasketId; ProductId; Quantity }
AddItemSucceeded { BasketId; ProductId; Quantity }
AddItemRevoked { BasketId; ProductId; Quantity }
ItemRemoved { BasketId; ProductId; Quantity }
CheckedOut { BasketId; Address }
Product { ProductId; Name; Price; }
// product events
ProductReserved { ProductId; Quantity }
ProductReservationFailed { ProductId; Quantity }
ProductReservationCancelled { ProductId; Quantity; }
Les commandes sont assez similaires aux événements, utilisant le nom impératif et non au passé.
En ce moment, cela fonctionne très bien indépendamment. J'émets une commande AddItem
, et elle crée un ItemAdded
événement sur l' Basket
ensemble qui fait ce qu'elle doit faire avec l'état du «panier». De même, pour le produit, la commande et les événements fonctionnent très bien.
Je voudrais maintenant combiner cela en un processus qui se passerait comme ceci (en termes de commandes et d'événements qui se produisent):
Le gestionnaire de processus ferait ce qui suit:
on BasketCreated: CreateShoppingProcess
on ItemAdded: ReserveProduct
on ProductReserved: SucceedAddingItem // does nothing, but needs to be there so that the basket knows it can check out
on ProductReservationFailed: RevokeAddItem
on RemoveItem: CancelProductReservation
on Checkout: CreateOrder // create an order and so on...
Les questions auxquelles je n'ai pas pu trouver de réponses définitives sont:
- Dois-je persister le gestionnaire de processus? Il semble que ce soit le cas, mais je ne suis pas sûr
- Si je le fais, je dois enregistrer les événements pour le gestionnaire de processus. Cependant, les événements qu'il écoute sont liés aux agrégats. Dois-je ajouter l'ID de processus à ceux-ci? Ai-je des événements séparés uniquement pour le gestionnaire de processus? Comment faire cela et rester aussi SEC que possible
- Comment savoir à quel panier les
ProductReserved
événements sont destinés? Est-ce OK d'avoir unBasketId
sur ceux-là aussi, ou est-ce une fuite d'informations? - Comment puis-je garder une relation entre les événements, comment savoir qui a
ItemAdded
produit quelProductReserved
événement? Dois-je transmettre unEventId
? Cela semble étrange ... - Dois-je implémenter le en
Basket
tant que gestionnaire de processus au lieu d'un simple agrégat?
Après quelques recherches supplémentaires, je suis arrivé à ceci: Une saga est quelque chose qui garde ses propres événements et écoute les événements de l'extérieur. Fondamentalement, c'est un agrégat qui peut également réagir aux événements qui se produisent en dehors de son propre petit monde.
Un gestionnaire de processus fonctionne avec les événements de l'extérieur et envoie des commandes. Son historique peut être reconstruit à partir des événements qui se sont produits sur les agrégats qui partagent un identifiant commun comme un correlationId.