lock of aggregate with two applications sharing a datasource

Imagine I have a spring boot application using axon with jpa store and embedded busses/gateways (supposibly with aggregate storage, not ES, but maybe that is not relevant).

I now run two nodes of the same app against the same DB.

Will an aggregate that command is handled on node 1 lock the aggregate, so I cannot handle a command for the same aggregate on node 2, or will they both handle and thus may produce locking exceptions?

Thanks
Jan

Hi Jan,

The lock on an aggregate is not maintained in the data source.
Or at least, not if you haven’t specified a different LockFactory for your Aggregate Repository.
The default LockFactory is the PessimisticLockFactory, which contains a map of aggregate id to lock.

That said, in the sketched scenario, you would thus load the aggregate on both nodes, potentially simultaneously if both receive a command for it.
If you are however using either AxonServer or the DistributedCommandBus, Axon as the RoutingStrategy in place which by default ensure a command for a given Aggregate Identifier will consistently be routed to the same node.

Thus, if you use one of the regular command distribution schemes, you should be safe. :slight_smile:

Hope this helps Jan!

Cheers,
Steven

Hi Jan,

if you use the GenericJpaRepository, Axon will actually put a write lock on the aggregate, so that other instances won’t be able to load it concurrently. If you’re using Event Sourcing, Steven’s reply is accurate, and you will load the aggregate on both nodes. However, when the second node inserts its changes, it will notice a conflicting event, and throw a ConcurrencyException.

Cheers,

Allard

Thank you both, this helps a lot.

Are you aware of any spring-boot based "Aggregate-Storage via JPA " and “no use of ES/axon server” examples?

Hi Jan,

We are in the process of updating the Reference Guide, to a point that ‘State-Stored Aggregate’ and ‘Axon without AxonServer’ examples will be part of the guide.
I however do not have examples at the ready like a GitHub repo or blog, like I assume you’re actually looking for.

The ConcurrencyException we’ve shared however is easily overcome by retrying the command at hand.
Issuing a retry of a command, because your commands are not consistently routed is a far easier approach to rely on than adjusting the Repository of your Aggregate.
So unless you were already looking to remove Event Sourcing entirely from your Aggregates, I’d likely suggest against this.

That’s my 2 cents.

Cheers,
Steven

Hi Jan,

if you do want to use state-stored aggregates and store them using JPA, all you need to do is annotate your aggregate with the correct JPA annotations. Axon + Spring Boot will recognize them and configure a GenericJpaRepository for you.

Cheers,

Allard

I want to retry the command at hand, but the command is processed on a separate thread and therefore the exception does not return inline if I try to catch the exception in a try, catch block. I also checked in the command handler, and the exception is not returned there either. What would be the best way to “retry” the command?

Hi Robert,

Retrying commands if there’s an exception can be configured by using a RetryScheduler you can set on the CommandGateway.
The specific implementation I think you should look for is the IntervalRetryScheduler.
Hope this helps!

Cheers,
Steven