1
votes

I have started planning for my first CQRS project with event sourcing and due to time constraints part of the model will remain in XML files. What I understand from DDD is that each update is done to an aggregate root and if I want to change another aggregate root from the first one (an event is raised in the domain) which first a command to modify the second aggregate. Each change has its own transactional boundary.

Now, what concerns me is if I have committed the change to the first aggregate (in a database) how do I handle the situation where the second aggregate (writing to a file in this case) fails?

I could issue a command to first update the file first (second aggregate) and then issue a command to change the first aggregate but once again I could have the second command fail but in this case here we have two separate commands which seem to go against the idea of events being raised in the domain that are handled as in the first case.

I suppose even if I wasn't using a file and all the changes were recorded in a database, there is a possibility that the second aggregate change could fail. Am I right to think this?

Still trying to get the concepts clear in my head so any help would be appreciated.

2

2 Answers

2
votes

The second aggregate can emit something like an UpdateFailed Event. This in turn can be handled by sending a Rollback Command to the first aggregate.

Do you have a concrete example? Often the need for a transaction that crosses aggregate boundaries can be solved by refining the model.

Update: Also have a look at a concept called "Saga". A saga can be a helpful coordinator for cross-aggregate processes like yours. A saga is basically an event handler that submits commands according to the events it receives. A saga can be just a stateless coordinator, but it can also be stateful, so it knows which commands would have to to be compensated in case a subsequent one has failed. Just google "CQRS Saga" and go from there. Especially the articles by Greg Young and Rinat Abdullin are a very helpful read.

1
votes

I think you have a question here more about transactional consistency then anything else. Since you have given no real business context for the conversation, it is hard to comment fully about the appropriate solution.

However, in general, if the second aggregate must update based on the command to the first aggregate, then perhaps they are in the same transaction (DDD 'Bounded-Context'). It is really hard to know without the context.

Otherwise, usually, if the second aggregate has subscribed to the first's event, that message is received in a transaction (this time belonging to the second aggregate), and if that operation can not be fulfilled, the handling of the event is rolled-back and re-tried (or pushed to another place for manual action (like an error queue)).

Does this help?