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.
This events will be fetched by AR2 and then processed.
Ohh, that sounds like a bad idea.
One more notice - in AR2 this layer would be read-only = needed to do some business logic inside AR2.
So looking at your picture, AR2 is writing out events (d,e,f), which says that AR2 is not read only -- which is good; read only aggregate roots don't make sense.
The usual pattern for what you seem to be trying to do here is to use a process manager to coordinate the activities of the two aggregate roots. The role of the process manager is to listen for events, and respond by dispatching commands.
In that picture, you would have something like the following:
Command(A) arrives at AR(1)
AR(1) loads its history [x,y,z]
AR(1) executes Command(A), producing events [a,b,c]
AR(1) writes its new history [x,y,z,a,b,c]
Events(a,b,c) are published
ProcessManager receives the events (a,b,c)
ProcessManager dispatches Command(B) to AR(2)
Command(B) arrives at AR(2)
AR(2) loads its own history [d,e,f]
AR(2) executes Command(B), producing events [g,h]
AR(2) writes its new history [d,e,f,g,h]
Events(g,h) are published
Trying to have two different aggregate roots share a common event history is really weird; it strongly suggests that your model needs rethinking (why are there two different authorities for the same fact? what happens when AR1 writes an event that violates the invariant enforced by AR2?).
But taking some of the state from one event, and making that an argument in a command sent to another aggregate; that pattern is pretty common. The process manager itself is just a substitute for a human being reading the events and deciding what commands to fire.
I always need current state of AR1 layer, even if AR2 is created from the scratch it needs to have content of layer from AR1. The layer would be read only.
There's no such thing as getting the "current" state of another aggregate; AR1 could be changing while AR2 is doing its work, and there's no way to know that. If that's not acceptable, then your aggregate boundaries are in the wrong place.
If stale data is acceptable, you can have the AR2 command handler query the state of AR1, and use that information in processing the command. If you are going to do that, I normally prefer to wrap the query in a Domain Service, which gives you an extra layer of indirection to work with (the domain model doesn't need to know how the service is implemented). In this design, AR2 doesn't see the AR1 events at all; AR2 passes some state to the domain service, and the domain service looks at the events to figure out the answer, and passes that answer back as a value that AR2 will understand.
Whittaker's solution isn't bad; once you recognize that the data is stale anyway, you have the option of deciding whether the state available at the time of creating the command is good enough. I'm of mixed minds on this -- putting everything into the command is nice, and really easy to understand. On the other hand, there is a larger window for a change to happen, and to some degree discovering the right data to use requires accessing state internal to the aggregate that can change while the command is in flight.
I much prefer designs where the aggregates aren't coupled, though.
But it seems that this is again sharing of data between the AR-s, since fat command will use data from layer from AR1 to supply to AR2
You might look into what Udi Dahan has to say about services as technical authorities. In that case, the data that gets shared is mostly limited to opaque identifiers.
Best Answer
Disclaimler: I'm only taking my first steps in the CQRS world, but I can offer my current understanding of the matter and we'll see if others confirm. All I write below has an underlying "as I see it" theme, and is not authoritative.
The 80% case
To answer your question, commands are indeed a point-to-point affair. When a command enters a controller (MVC webapp), that controller then asks a command dispatcher to find one and only one apropriate command handler, and delegates the work to that handler.
Why not publish?
It's a question of responsibility. If something sends a command, it entails expectation that it will be fulfilled. If you simply publish and hope that something somewhere picks it up and acts on it, there is no guarantee that this will be the case. By extrapolation, you also don't know if multiple handlers don't decide to act on a command, possibly resulting in the same change being applied more than once.
Events, on the other hand, are informative in nature, and it's reasonable to expect zero, two, or more components to be interested in a particular event. We don't really care in the scope of making the requested change.
Example
This could be compared to real life. If you have three children, walk into a room and simply shout "Clean the bathroom," you have no guarantee that someone will, and perhaphs if it won't be done twice (if you have obedient children that is ;-) You should fare better if you assign a specific child to do what you want done.
When that child finishes its job however, it's convenient if it shouts out "bathroom has been cleaned," so that everyone who wants to brush their teeth knows they can now do so.