Saga that depend on events from the past
I have a question how to deal with a saga where the decision making depends on an event that was published before the saga was created.
Here is an example to illustrate my issue:
Imagine I have a CustomerAR and a OrderAR. When the customerAR is created a validation process starts, the result of that process is the amount of an order that the customer is free to spend without special authorization. I will not go into detail about this process because it's out of context. When the amount is calculated a command is sent to the the CustomerAR with the calculated amount and the CustomerAR publishes an event (CustomerMaxOrderAmountEvent) with that value. So far so good.
Then a few weeks later the customer places an order. The OrderAR is create开发者_StackOverflow社区d and starts my OrderSaga. The saga waits until the order is created completely and then has to make a decision if it needs to send an AutorizationCommand for that order. To make that decision it has to know if the CustomerMaxOrderAmountEvent is published and the value of the amount. Normally the OrderSaga will also subscribe to the CustomerMaxOrderAmountEvent, but the problem is this event will never occur because it already did in the past.
How should I deal with this. Should I query the read model to know the value, should I send a command to get the value, should I make a reference to the CustomerAR, should I replay all historic events in the saga so he knows the history already.
UPDATE
Please note that it's about the concept not about this concrete example. The example is pure for clarification of the problem: "2 non related aggregate roots that are not part of the same bounded context."
Thankful for help.
Melvin
I would go for simpler solution - just add this information (for example in a form of HasCustomerReachedMaxOrderAmount
) to the event that starts the Saga.
The second option I'd choose is to prepare a read-model designed to be used with the Sagas and query data from there, but I'd gather all the required information even before the saga is started. This enrichment could be performed by a handler to the original event raised by AR as this is not something that is part of Aggregate/Bounded Context.
In most cases however basing on data passed with events is sufficient due to the fact that Sagas should contain business logic only in form of process. This very often means that you might end up with more then one Saga (to follow your example OrderSaga
and OrderWithMaxAmountSaga
).
All that said, considering the sample scenario you've provided, I think that decision whether order requires authorization or not should rather be part of your domain itself and passed while starting saga.
I'd model this scenario like this - CustomerAR
calculates max amount; customer places an order -> OrderAR
is created with the information about max amount for this customer, Order
verifies if it needs additional authorization -> Saga
get started. The point is that information about max amount is important for both CustomerAR
(where it can change) and OrderAR
(where it's immutable).
I'm just starting to dabble with DDD and I don't intend to repeat anything that kstaurch said, but here are some thoughts I had looking at your scenario:
What about making the max order amount part of the billing information? That has to be gotten somewhere and I'm sure you take care of the condition where payment processing is denied.
What if the saga always sends the authorization command, but it's the authorization part that handles the max order screen? If you're saying "If the amount is over $X then get authorization", maybe your business model also thinks of it as "If it's under $X, auto-approve." The benefit is that all approval considerations (including whether to get approval) can be moved to an approval entity or saga.
精彩评论