Complex Event Processing

Maybe slightly off topic but is there a recommended approach/possibility to do complex event processing using Axon Framework together with Axon Server?

I have this use case in a proof of concept for research purposes in which I would like to group different types of events into one single, “aggregated” event being handled by another µ-service.

TL,DR;
The “source” events are created depending on the actions taken by the user so they come in an unpredictable order and timing. Depending on the user interaction between 1 and 6 event types are generated. Each of them can have between 0 and N instances fired depending on what the user does. (Arguably not the best design.) Each event has an unique client id and an event date. All events for the same id and the same date should be grouped into a new “aggregate” event.

It seems to me the use of a dedicated streaming event processor with a PropertySequencingPolicy (using the combination of id and date probably) could do the trick, but it seems a bit far fetched (and abusive for the initial purposes) by doing so.

As an alternative, I considered the abuse of sagas for this purpose but I think this won’t do the trick since I don’t know which type event is sent first on a certain date by a certain client. Second, I don’t know when the last event for that user on that day is fired. In other words, there is no single trigger to start or end the saga.

A third option might be offloading the complex event processing to an external solution and use something like Kafka Streams. Being a possible solution, this would increase complexity of the solution a lot since in the end (in production) we would need both an Axon Server cluster and Kafka cluster available which might overkill in our PoC.

Thank you for reading/responding.

Hi Kurt, could you maybe expand on the use case?

I don’t see the problem with the saga. You could have multiple events that could create a saga, by default, it would not create a saga if one already exists. You could end the saga by either using a deadline manager or a scheduled event. If that is scheduled for the end of the day, you are sure to have seen all the events for that day by that user.

Hello Gerard,

I would use the concept of event processing to do two tasks.

  • First there are a number of event types providing each a part of the information I need in my final “aggregated” event. That final event acts as some kind of summary event. Other parts of the application don’t need the individual information of all those events, but only a summarized “state”.
  • Second I need to “enrich” the “aggregated” event with data provided by an external service using a REST API call.

The aggregated event is then (after the enrichment is completed or when a reasonable amount of time to allow the user to provide additional data is passed) used by other part of the application to do its job. At this stage, the “summary” represented by the event will be stored in a NoSQL database for future use by an AI solution during its learning phase. In the future, the same event might be used to parse a CSV file or Parquet file for the same purpose.

I did not realize that multiple events could create a saga and one is only created when no other exists. As such, a saga might be usable for the intended use case after all. Elaborating on this approach, does the framework support @SagaEventHandler(associationProperty = "clientId, date") to associate multiple property value to the saga event handler, or can this be achieved without the annotation attribute and using SagaLifecycle.associateWith(key, value) explicitely.

Thanks!

Only the first association, the one present on the @StartSaga annotated method, is set for you by Axon Framework.
Apart from that, you will consciously need to make other associations through the SagaLifecycle#associateWith method.
Through this, you can associate with N different contexts / aggregates / properties you see fit.

By default, associations come from properties in the event itself.
You can change the association resolver to check MetaData, too, if necessary. Or, you can provide other custom implementations to resolve your associations.

By the way, it sounds like you’re looking for a form of Context Mapping (e.g., an anti-corruption layer).
Is that a fair assumption?
To break your request down, it sounds like there’s some trigger event that requires you to share an accumulation of data (in the form of an event) to another context.

You can do this with a Saga, sure. Any regular Event Handling Component would work too, but you’d likely query the data required to enrich the “trigger event.”

If that data comes from another Event Handling Component, sure, that’s fine.
But, in essence, that’s not the concern of this Context Mapper.

A Saga does make it easy if you know all the associations and as long as you will end it’s lifecycle eventually.

That’s my two cents on your scenario. I hope it helps you further, @KDW!