Estoy trabajando en una pequeña aplicación de ejemplo para aprender los conceptos de CQRS y el abastecimiento de eventos. Tengo un Basket
agregado y un Product
agregado que debería funcionar de forma independiente.
Aquí hay un pseudocódigo para mostrar la implementación
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; }
Los comandos son bastante similares a los eventos, usan el nombre imperativo y no el tiempo pasado.
En este momento estos funcionan bien independientemente. Emite un comando AddItem
y crea un ItemAdded
evento en el Basket
agregado que hace lo que necesita hacer con el estado de la 'Cesta'. Del mismo modo, para el producto, el comando y los eventos funcionan bien.
Ahora me gustaría combinar esto en un proceso que sería algo así (en términos de comandos y eventos que suceden):
El administrador de procesos haría lo siguiente:
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...
Las preguntas a las que no pude encontrar respuestas definitivas son:
- ¿Necesito persistir en el administrador de procesos? Parece que sí, pero no estoy seguro
- Si lo hago, necesito guardar los eventos para el administrador de procesos. Sin embargo, los eventos que está escuchando están vinculados a los agregados. ¿Añado el ID del proceso a esos? ¿Tengo eventos separados solo para el administrador de procesos? Cómo hacer esto y mantenerse lo más SECO posible
- ¿Cómo sé para qué cesta son los
ProductReserved
eventos? ¿Está bien tener unBasketId
sobre eso, o es esa información que se filtra? - ¿Cómo mantengo una relación entre eventos, cómo sé qué
ItemAdded
produjo quéProductReserved
evento? ¿Paso a lo largo de unEventId
? Esto parece extraño ... - ¿Debo implementar el
Basket
como administrador de procesos en lugar de un agregado simple?
Después de un poco más de investigación llegué a esto: una saga es algo que mantiene sus propios eventos y escucha eventos desde el exterior. Básicamente, es un agregado que también puede reaccionar a eventos que suceden fuera de su propio pequeño mundo.
Un administrador de procesos trabaja con los eventos desde el exterior y envía comandos. Su historia se puede reconstruir a partir de los eventos que ocurrieron en los Agregados que comparten un identificador común como un ID de correlación.