“One thing to take special care with is to *never* replay your events on the EventBus. You're very likely to have handlers there that don't support replying, such as saga's. Replaying them would cause commands to be generating, changing your application's state, instead of rebuilding it.”“In my design, a single Event Handler is responsible for updating one or more related tables. If I want to rebuild these tables, I clear them and replay all events from the event store on that single handler.”
Without understanding this mutually exclusive use cases, an infinite loop may be created in your head. It took me a while to break out of it – thanks to `ExhaustiveThinkingException`. :)One has to understand that Simulation and State Replay are mutually exclusive use cases (at least in CQRS/ES):- State Replay is replaying Events and forcing the system into exactly the same old state which it had at the specific point of time in the past.- Simulation is replaying Commands and letting the system to recompute its new state based on the same sequence of input commands.The crucial difference is that the resulted states in this use cases can be different.Simulated and Replayed states may diverge due to command processing order, fixed bugs, any other system differences between the time of recording and the time of replaying...
I'll emphasise.
Simulation and State Replay are different to each other the same way as Commands and Events are different in CQRS/ES.
There is one-to-one correspondence (individually or in pairs):- “Simulation” ~ “Command”- “State Replay” ~ “Events”- (“Simulation”, “State Replay”) ~ (“Command”, “Events”)To avoid confusion from now on:- For clarity, terms “Command Replay” and “Event Replay” will mostly be used - they belong to CQRS/ES ubiquitous language. They describe exactly what's going on in implementation.- Terms “Simulation” and “State Replay” will only be used to reference the two distinct use cases. It just happened that one use case replays Commands and another replays Events if CQRS/ES is used.
It is impossible to replay both at the same time.Why?It's obvious.It will create a mess.
Replayed commands will generate new events (similar to old events which are already part of event store) as a result of replaying the same commands.
How replaying old events fit together with new events (generated by replayed commands)?
It does not make any sense even if it can be done technically somehow.
For the same reason why Command and Events cannot be replayed together, Commands must be suppressed when Events are replayed.
Any Command in response to Event processing creates the same mess in replay mode as described before. Command generates new Events in addition to similar old Events being replayed.In other words, during Event Replay, an aggregate state must be fed and rebuilt from event store only. This can be repeatedly seen as warning (unless it is supported by suppressing commands during event replay):
“One thing to take special care with is to *never* replay your events on the EventBus. You're very likely to have handlers there that don't support replying, such as saga's. Replaying them would cause commands to be generating, changing your application's state, instead of rebuilding it.”
Wait a minute!I've just repeatedly said that Commands and Events cannot be replayed at the same time, haven't I?Yes. In its simple example for single aggregate, it is obviously not possible to make sense.However, when the system is broken down into pieces carefully, things can become more flexible:- Some aggregates can use “State Replay” via replaying their Events.- Some aggregates can be under “Simulation” via replaying their Commands.- Some aggregates may even process live (not simulated) Commands from user or external system.It all may become complex to debug and reason about, but the point is that conceptually it is not prohibited and can co-exist.There are two different processes incompatible in their nature. By selectively replaying Commands or Events depending on the specific subsystem (Bounded Context with its own set of Aggregates?) hybrid solution is possible.
I always thought about the hybrid solution while unable to separate these use cases. This forced me to avoid calling messages by their exact name - I felt problems. So, instead, I introduced term “frames” to hide real type of replayed messages (see the first post).
I was stuck and confused. Not so anymore.
This term probably sounds insane for any CQRS/ES veteran, but look – again, I carefully surrounded it by quotes. :)There is a need to store commands if they are supposed to be replayed for "Simulation" later.Now, there is a problem to record commands because they are always addressed to specific aggregate (by their id):- There is always only single destination per command – an aggregate.- And the aggregate is busy with domain logic. The aggregate is not supposed to be the server to record commands.However, I can think of some way to wrap all command received by this aggregate inside a special event (“Command X was captured”).There are just nuances like:- Should we (somehow) intercept commands on the way to aggregate and call the special events as “Command X was sent”?- Or should we record commands when aggregate already received then and call the special events as “Command X was received”?I like the first “was sent” type of event to capture the command because we can replay (“simulate”) the fact of sending command even if it never reached the aggregate.But these are not important details for now.The point is that any command can be wrapped and stored inside event store.
The special “command store” is not required.
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Yes. I also thought about this...
In analogy with jungle:
Why do I need to regrow all trees and animals in the jungle every time movie is replayed if all people care about is that flat rectangular TV screen showing the documentary?
Even if I could satisfy "Record and Replay" requirement using projection, I still kept on (unintentionally) mixing in another one - simulation, which is in the jungle analogy:
All the trees and animals are actually being regrown in controlled environment under the influence of some fake sun and some fake atmosphere.
Now, when I already separated these two use cases, I don't see necessary exploring "generic record and replay of everything".
However, I will still need to implement Simulation (replaying of Commands) which is simply going to be a different/separate and more straightforward solution now.
This! This clarification is actually new point to me.Although I did think about pushing only replayed events (not commands) and only to some sort of projection (without feeding anything else within the system), but I still amaturely imagined that I'm going to implement some control on top of Event Store to release one "frame" at a time. I never had idea that I can simply feed all events to the projection in one shot and then implement control of that projection for the replay of "frames".Just to feel the difference:- Messing with some wrapper around Event Store to implement this additional responsibility of sending "frames" one by one at their right time of replay.- Just use framework as it expects to be used. Push all "frames" to another service in one shot. Enhance frontend with replay controls integrating the new service (the projection).