I'm starting to work on moving my Axon 2 application to Axon 3. It's mostly straightforward but I'm not sure what to do with some of my event handlers, specifically ones that maintain my query model.
In order to avoid having to rebuild every table in the entire query model whenever a change happens to a specific piece of it, I have a global registry of which event handlers should do work during a replay. Before a replay happens I tell the registry which event handlers I care about, then kick off the replay. Every event listener that maintains part of my query model is a subclass of this helper class:
public class AbstractReplayAwareExporter implements ReplayAware {
private transient boolean enabled = true;
public void beforeReplay() {
enabled = EventReplayMigration.shouldHandleReplay(getClass());
}
public void afterReplay() {
enabled = true;
}
public void onReplayFailed(Throwable cause) {
enabled = true;
}
/**
* Returns true if the event handler should process incoming events. This will always be true
* during normal operation, but during replays it may be false if a migration has specified
* that it only needs events to be handled by specific event handlers.
*/
protected boolean isEnabled() {
return enabled;
}
}
Each event handler method is wrapped in an "if (isEnabled())" check. So all my event handlers actually get invoked on a replay, but the ones I don't care about end up immediately returning without doing any work.
How do I achieve the same effect in Axon 3? ReplayAware doesn't exist and more generally with the TrackingEventProcessor it seems like there is no longer a distinction between "replay old events" and "catch up with events that are in the event store but we happen to have not processed yet."
The best idea I've come up with so far is to query the ID of the most recent event before kicking off the replay, then have an event handler that watches for that event to go by and sets a "replay is done" flag in some central place. But that seems like more of a hack than it should be, and I'm also not confident that it'd be deterministically correct in the presence of asynchronous event handlers.
Any better approaches?
-Steve