You shouldn't delete the events from your event store. These represent something that happened.
If something happens now, then you should know it too, therefore add an event that will force your aggregate to go back to some previous state. That's a pity to delete information from your database.
think about the example of the cart from greg young and the removed items. May be tomorrow the information of compensating action might be of any value..
As for the saga, every thing is correct, as far as I know myself. You should think of the saga as of a state machine. It does only that.
It is a Command the saga is issuing to tell the aggregate to do something. Of this action there will be an event.
This event might be the corrective action you need, or might need to be denormalised in a view so that some user will see it to decide what to do.
It depends on your business rules. Either, there is an easy fix : the aggregate root knows that in such case , you do that, or the choice is too complex to be done programmatically ( development cost are too high) and therefore, you might propose this to some user, who might choose between different action.
Everything depend on the context of the compensating action. This is pure business rules. What should we do in this case or that case. This is something to ask your domain expert, and then choose with him, if it is better to develop an automatic solution or if the solution is to ask the user Ronald R., because he is the one to answer this question usually.
Review what Rinat Abdullin wrote about evolving business process. In particular, notice his recommendation for developing a business process in a fast changing environment -- a process manager is "just" an automated replacement for a human being staring at a screen.
My own mental model of a process manager is that it is an event sourced projection that you can query for a list of pending commands.
Do I need to persist the process manager? It seems like I do, but I'm not sure
It's a read model. You can rebuild the process manager from the history of events each time you need it; or you can treat it like a snapshot that you update.
If I do, I need to save the events for the process manager.
No - the process manager is a manager. It doesn't do anything useful on its own; instead it tells aggregates to do work (ie, make changes to the book of record).
How do I know what basket the ProductReserved events are for? Is it OK to have a BasketId on those too, or is that leaking info
Sure. Note: in most "real" shopping domains, you wouldn't insist on reserving inventory before processing an order; it adds unnecessary contention to the business. It's more likely that your business would want to accept the order, then apologize in the rare case that the order can't be fulfilled in the required time.
How do I keep a relationship between events, how do I know which ItemAdded produced which ProductReserved event?
Messages have meta data - in particular, you can include a causationIdentifier (so you can identify which commands produced which events) and a correlationIdentifier, to generally track the conversation.
For instance, the process manager writes its own id as the correlationId in the command; the events produced by a copy the correlation id of the command, and your process manager subscribes to all events that have its own correlationId.
Should I implement the Basket as a process manager instead of a simple aggregate?
My recommendation is no. But Udi Dahan has a different opinion that you should review; which is that CQRS only makes sense if your aggregates are sagas -- Udi used saga in the place where process manager has become the dominant spelling.
should process managers retrieve aggregates?
Not really? Process managers are primarily concerned with orchestration, not domain state. An instance of a process will have "state", in the form of a history of all of the events that they have observed -- the correct thing to do in response to event Z depends on whether or not we have seen events X and Y. So you may need to be able to store and load a representation of that state (which could be something flat, or could be the history of observed events).
(I say "not really" because aggregate is defined vaguely enough that it's not completely wrong to claim that list of observed events is an "aggregate". The differences are more semantic than implementation -- we load process state and then decide what messages to send to the parts of the system responsible for domain state. There's a bit of hand waving going on here.)
So the PM does not need to use one type of state management over another because it is only responsible for doing stuff live and never during replays?
Not quite - state management isn't a do-er, it's a keeper tracker of-er. In circumstances where the process manger shouldn't emit any signals, you give it inert connections to the world. In other words, dispatch(command)
is a no-op.
Best Answer
The best way: write your domain model such that at most once handling is built into the business logic.
Marc de Graauw, from Nobody Needs Reliable Messaging:
But that's not the sort of example you are considering;
In a situation where MUST; I'd normally look for at-least-once handling of the event. The process keeps track of both which emails are required, and which have been acknowledged.
For example, the process subscribing to
OrderCreated
,EmailSent
, andEmailTimedOut
. On "order created", we dispatch a command to send the email, and another to publish the timeout event. Upon receiving the timeout, we check to see if the EmailSent message has appeared -- if not, we resend.Review in detail the cost to the business of the different failure modes. If you MUST send the email, then you need the ack to know you have done so. If the ack can get lost, then you need to resend -- what's the cost to the business of sending that email more than once? Don't sign up for expensive perfection when failure is rare and low cost.
Jonathan Oliver: Messaging: At Least Once Delivery
See also: https://stackoverflow.com/q/416551/54734