Estou trabalhando em um aplicativo de exemplo pequeno para aprender os conceitos de CQRS e fornecimento de eventos. Eu tenho um Basket
agregado e um Product
agregado 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 AddItem
e ele cria um ItemAdded
evento no Basket
agregado 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
ProductReserved
servem os eventos? Tudo bem ter umBasketId
também, ou essas informações estão vazando? - Como mantenho um relacionamento entre os eventos, como sei qual
ItemAdded
produziu qualProductReserved
evento? Eu transmito umEventId
? Isso parece estranho ... - Devo implementar o
Basket
como 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.