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
created 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
OrderSagaandOrderWithMaxAmountSaga).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 –
CustomerARcalculates max amount; customer places an order ->OrderARis created with the information about max amount for this customer,Orderverifies if it needs additional authorization ->Sagaget started. The point is that information about max amount is important for bothCustomerAR(where it can change) andOrderAR(where it’s immutable).