Estou trabalhando em um aplicativo de exemplo pequeno para aprender os conceitos de CQRS e fornecimento de eventos. Eu tenho um Basketagregado e um Productagregado que deve funcionar de forma independente.
Aqui estão alguns pseudo códigos para mostrar a implementação
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; }
Os comandos são bem parecidos com os eventos, usando o nome imperativo e não o pretérito.
No momento, eles funcionam bem de forma independente. Emito um comando AddIteme ele cria um ItemAddedevento no Basketagregado que faz o que é necessário com o estado do 'Basket'. Da mesma forma, para o produto, o comando e os eventos funcionam perfeitamente.
Agora eu gostaria de combinar isso em um processo que seria algo assim (em termos de comandos e eventos que acontecem):
O gerente de processo faria o seguinte:
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...
As perguntas para as quais não consegui encontrar respostas definitivas são:
- Preciso persistir no gerenciador de processos? Parece que sim, mas não tenho certeza
- Se sim, preciso salvar os eventos para o gerenciador de processos. No entanto, os eventos que está ouvindo estão vinculados aos agregados. Eu adiciono o ID do processo a esses? Tenho eventos separados apenas para o gerente de processos? Como fazer isso e manter o mais seco possível
- Como sei para que cesta
ProductReservedservem os eventos? Tudo bem ter umBasketIdtambém, ou essas informações estão vazando? - Como mantenho um relacionamento entre os eventos, como sei qual
ItemAddedproduziu qualProductReservedevento? Eu transmito umEventId? Isso parece estranho ... - Devo implementar o
Basketcomo um gerenciador de processos em vez de um simples agregado?
Depois de mais algumas pesquisas, cheguei a isso: uma saga é algo que mantém seus próprios eventos e ouve eventos de fora. Basicamente, é um agregado que também pode reagir a eventos que acontecem fora do próprio mundinho.
Um Gerenciador de processos trabalha com os eventos externos e envia comandos. Sua história pode ser reconstruída a partir dos eventos que ocorreram nos agregados que compartilham um identificador comum como um ID de correlação.