Sto lavorando su una piccola applicazione di esempio per apprendere i concetti di CQRS e di gestione degli eventi. Ho un aggregato Basket
e un aggregato Product
che dovrebbe funzionare in modo indipendente.
Ecco qualche pseudo codice per mostrare l'implementazione
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; }
I comandi sono abbastanza simili agli eventi, usando il nome imperativo e non il passato.
In questo momento questi funzionano bene indipendentemente. Rilascio un comando AddItem
e crea un evento ItemAdded
sull'aggregato Basket
che fa ciò che deve fare con lo stato del 'Cestino'. Allo stesso modo, per il prodotto il comando e gli eventi funzionano bene.
Mi piacerebbe ora combinare questo in un processo che farebbe qualcosa di simile (in termini di comandi ed eventi che accadono):
Il gestore del processo dovrebbe eseguire le seguenti operazioni:
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...
Le domande a cui non sono riuscito a trovare risposte definitive sono:
- Devo mantenere il gestore dei processi? Sembra come me, ma non sono sicuro
- Se lo faccio, ho bisogno di salvare gli eventi per il gestore dei processi. Tuttavia, gli eventi che sta ascoltando sono legati agli aggregati. Devo aggiungere l'id del processo a quelli? Ho eventi separati solo per il responsabile del processo? Come fare questo e mantenere il più ASCIUTTO possibile
- Come faccio a sapere a che cosa servono gli eventi
ProductReserved
? Va bene avere unBasketId
anche su quelli, o sono informazioni che perdono? - Come faccio a mantenere una relazione tra gli eventi, come faccio a sapere quale
ItemAdded
ha prodotto quale eventoProductReserved
? Passo unEventId
? Questo sembra strano ... - Devo implementare
Basket
come gestore dei processi invece di un semplice aggregato?
Dopo un po 'di ricerca sono arrivato a questo: Una Saga è qualcosa che mantiene i suoi eventi e ascolta gli eventi dall'esterno. Fondamentalmente, è un aggregato che può anche reagire agli eventi che accadono al di fuori del proprio piccolo mondo.
Un Process Manager funziona con gli eventi dall'esterno e invia i comandi. La cronologia può essere ricostruita dagli eventi che si sono verificati sugli Aggregati che condividono un identificatore comune come un ID di correlazione.