Simple command bus and concurrency exception

Hello,

I am currently working on a project where I am using the following technologies:

  • Axon Framework version 4.5.15
  • Spring Boot 2.3.10.RELEASE
  • Java 8

My application is running on 4 pods in a production environment. It utilizes PostgreSQL as an event store. I’m using the simple command bus to dispatch commands. In this project, I have defined an aggregate with commands and event sourcing handlers.

However, sometimes, I am encountering a ConcurrencyException when handling a command, specifically:

“Command resulted in org.axonframework.modelling.command.ConcurrencyException: An event for aggregate [<aggregate_id>] at sequence was already inserted.”

Here’s an example code snippet of my aggregate definition for reference:

@Aggregate
public class MyAggregate {

    @AggregateIdentifier
    private String aggregateId;

    @CommandHandler
    public void handle(SomeCommand command) {
        AggregateLifecycle.apply(new SomeEvent());
    }

    @EventSourcingHandler
    public void on(SomeEvent event) {
        // Perform some logic
    }
}

How can I guarantee that the specific aggregate will handle one command at a time, even if multiple commands are dispatched on different pods simultaneously to the same aggregate instance using the simple command bus? Do i need to use a different command bus implementation?

I appreciate any guidance or suggestions on implementing a solution for this scenario.

Thank you in advance!

Your guess here, @alainelkhoury, is completely correct.
The SimpleCommandBus is incapable of routing commands consistently to the same node simply because it does not communicate outside of the JVM.

Because the SimpleCommandBus cannot perform this coordination, there’s a window of opportunity that any of your 4 nodes will load a specific aggregate instance for command handling.
One of those instance will, however, be faster than the others when it publishes events.
This is where your ConcurrencyException comes from: two (or more) instances try to insert an event at the same position, wherein one fails, leading to said exception.

You are thus inclined to use a distributed command bus.
Your options here are:

  • Axon Server - this means you will be done for event storage, event routing, command routing, and query routing in one go. Hence, you can drop your custom event store logic in PostgreSQL.
  • The DistributedCommandBus through our Spring Cloud extension - you are required to select a Spring Cloud implementation that suits your environment.
  • The DistributedCommandBus through our JGroups extension.

I trust the above will help you further, @alainelkhoury!

PS, note that Axon Framework is already on 4.8.0.
Upgrading is always a recommendation ensuring you do not face any bugs that have already been solved. Added, you get the benefit of using newer features from Axon Framework.

1 Like

Thank you for your helpful reply!

1 Like