Selectively enabling event handlers during replay in Axon 3?

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

Hi Steve,

the concept of “replay” as known in Axon 2, has disappeared. In Axon 3, tracking processors can be “Reset” to start tracking from the beginning (and in the near future from any other point in time). Event Handlers should organized in a way that “replayable” (or “resettable”) handlers are assigned to different processors than those that aren’t.

In your case, where you want to be able to reconstruct part of the query model, make sure each query model updater is assigned to its own TrackingProcessor (or at least in small groups). Then you can reset a specific Processor.

Alternatively, consider the “changed” projection actually a new one. Build it next to the existing ones, and remove the old one when the new processor has caught up with time.

Hope this helps.
Cheers,

Allard