cqrsevent-sourcingaxon

How to handle dependent EventHandlers?


I've got an event sourced AxonFramework application, which needs to make calls (on/after certain events) to external services. These calls require data from projections, which the event updated/produced.

At first I had the call to the external service and the creation of the projection in the same handler. This assures that the data is persisted and available, but makes it impossible to replay/rebuild the projection, because the external services must not be called again.

Since having the saving of the projection and the service call in the same handler is not an option anymore, I came up with 3 possible solutions:

  1. Add some kind of check right before the service call, which will then be retried if the data is missing. Retrying is already built into it.
  2. Always merge the data from the event with the current state of the projection to ensure that we'll always use the most uptodate data.
  3. Issue a command in the projection event handler, which requires a service call. The command handler will check if the service needs to be called (a flag for instance) and only emits an specific event if so. This event will then be handled by the event handler with the service call.

All 3 come with trade-offs. But I would prefer option 3.

Which one would you choose? Maybe there's an 4th option which I didn't came up with.


Solution

  • Axon allows you to check whether events are being "replayed", or if it's the first time a handler is being called with that particular event.

    Basically, you can add a parameter of type ReplayStatus to your event handler. The isReplay() method on it will indicate whether the event is part of a replay, or not.

    You can find more about this in the documentation: https://docs.axoniq.io/reference-guide/axon-framework/events/event-processors/streaming#replay-api

    Ultimately, the best is to entirely separate replayable projections from non-replayable side-effects. In case that's not feasible, the ReplayStatus parameter is there to help.