Tracking Event Handler tracking "external" event store

Hi Axon Users,

first I’d like to thank the creators of the Axon Framework for open sourcing such a nice piece of software! It is very much appreciated.

So I have just started to explore the Axon Framework as well as Spring Boot (I am rooted in the JEE world) so the answer to my question might be obvious but I wasn’t fully able to derive the answer from the docs. Lets use an example to illustrate it.

Lets say I have a application A that takes care about everything directly related to accounts and another app B that takes care about everything related to orders.

They both have their own separate event store databases and use CQRS with Event Sourcing with Axon 3 to do their job. Now app B would naturally be interested in some events from app A. So the question is how would I setup a tracking event handler within app B?

Right now the Axon Spring Boot Starter is doing all the magic in the background to wire up the event store, etc to its own event store. So how would I add a second “external” event store sitting in a different DB for app B that can be used by only a few Tracking Event Handlers?

Or maybe this is not the right way to do this at all? Any pointer in the right direction is welcome.

Thanks for your help and Happy New Year,

Thorsten

I would not have them piggyback each others event store. The axon events are internal to each bounded context. If A is interested in certain state changes within B then B should broadcast explicit external events for this on a separate message broker. If you find that A really depends on a lot of state changes in B then they might not be separate bounded contexts and you should consider merging into one application.

Jorg

Hi Thorsten,

I partially agree with Jorg. You don’t want to forcefully share events between components. Using a messaging system in between the two gives you more freedom to decide what to share.
However, it also gives you the drawback of needing to use an ephemeral messaging system (even if you use Kafka, you probably don’t want to store the events forever, again…). Sharing your Event Store actually makes it possible to track events and go back “to the beginning of time”.

Right now, the only way to support tracking two different Event Store, is by defining two event store instances in your application. Make sure to mark one of them @Primary, so that one gets injected in your application by default. On the other one, you probably want to configure a read-only use account, so you don’t mess it up by accident.

Regardless of the option you choose, it is wise to carefully select the events which you want to send outside of your own bounded context. Quite often, most events only make sense withing this boundary. A typical example would be the publishing of articles. Imagine: ArticleCreated, ArticleUpdated, ArticleSubmittedForApproval, ArticleRejected, ArticleUpdated, … ArticlePublished. In this flow, for other contexts, there is no “article” until the moment of the “articlePublished”. Until then, it’s just work in progress. So probably, you don’t want to share any, but the ArticlePublished event.

Hope this helps.
Cheers,

Allard

Hi,

But the beginning of time as you refer to it Allard is normally different per bounded context. So upon reception of an external event, the second bounded context would just fire a command to do its thing. When a replay in one BC also requires replay of the other BC then again it's probably an indication that they should not be separated. Would you replay all linked orders if the account AR is replayed? Can't think of any example right now where this would be a good idea.

Jorg

Hi Allard and Jorg,

thanks for your quick answers. Thinking more about it I actually believe using Axon only for intra bounded context CQRS/ES makes sense for me.
So I’ll most likely use a different messaging tech like Kafka+Avro for inter bounded context messaging. This will potentially encourage a cleaner decoupling between multiple bounded contexts and avoid the exposure of all internal events to external subscribers because they will get their own message schemas. Most likely a similar subset of the internal ones.

Again thanks to both of you for the insight.

Thorsten

Hello Thorsten

What about this approach:

Bounded context B “owns” tracking token. It sends pull request with this token and optional event filter expression to context A, which constructs tracking processor in its own context on behalf of B, pulls events happened since tracking token, filters them if needed, also paging can be applied here, then returns list of events together with new token to B. B stores new token and processes events. If something happens in-between, like network failure, both systems are still in consistent state. Also, this flow is idempotent, in the sense that same token and filter expression will correspond to the same set of events.

I’m just not sure how costly is creation of new tracking processor per request, but I hope that it’s not too high.