I realize the above question probably raises a few 'what??'s, but let me try to explain :
I'm trying to wrap my head on a couple of related concepts, basically the Saga-pattern ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf) in combination with Event-sourcing (A DDD-concept: http://en.wikipedia.org/wiki/Domain-driven_design)
A good post that wraps it together: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/
I'm getting to the question in a minute, but I think I have to try to summarize what I understand of it first (which might well be wrong, so please correct if that's the case) since this might well impact why I'm asking the question to begin with:
- The Saga pattern is a sort of broker that given an action (end-user, automated, etc. essentially anything that is going to change data) divides that action up in business activities and sends each of these activities as messages to a Message Bus which in turn sends it to the respective aggregate roots to be taken care of.
- These aggregate roots can operate completely autonomously (nice separation of concerns, great scalability, etc. )
- A Saga-instance itself doesn't contain any business logic, that is contained in the aggregate roots it sends activities to. The only 'logic' contained in the Saga is 'process'-logic, (often implemented as a Statemachine), which determines based on actions received (as well as follow-up events) what to do (i.e: what activities to send)
- The Saga-patterns implements a kind of distributed transaction pattern. I.e: when one of the aggregate roots (which again work autonomously, without knowing of eachothers existense) fails, the entire action might have to be rolled back.
- This is implemented by having all aggregate roots, upon completion of their activity report back to the Saga. (In case of success as well as error)
- In case all aggregate roots return a success, the internal statemachine if the Saga determines what to do next (or decides it's done)
- In case of failure, the Saga issues to all aggregate roots that took part in the last action a so called Compensation Action, i.e: an action to undo the last action each of the aggregate roots did.
- This might be simply doing a 'Minus 1 vote' if the action was "plus 1 vote' but it could be more complicated like restoring a blogpost to it's previous version.
- Event-sourcing (see the blogpost combining the two) aims to externalize saving the results of each of the activities that each of the aggregate roots undertake to a centralized Event Store (the changes are called 'events' in this context)
- This Event store is the 'single version of the truth' and can be use to replay the state of all entities simply by iterating the events stored (essentially like an event log)
- Combining the two (i.e: letting aggregate roots use Event-sourcing to outsource saving their changes before reporting back to the Saga) enables lots of nice possibilities, one of which concerns my question...
I felt I needed to get this off of my shoulder, since it's a lot to grasp in one go. Given this context/mindset (again, please correct if wrong)
the question: When an aggregate root receives a Compensate Action and if that aggregate root has outsourced it's state-changes using Event-sourcing, wouldn't the Compensate Action in all situations just be a delete of the last event in the Event Store for that given Aggregate Root? (Assuming the persist-implementation allows deletes)
That would make sense to me a lot (and would be another great benefit of this combination) but as I said I might be making these assumptions based on a incorrect/incomplete understanding of these concepts.
I hope this didn't get too long-winded.