Is a CommandHandler function locked the same way an eventhandler is?

I want to perform database operations from within either a command handler or event handler – my question is - does the command handler lock on a thread in the same way that an event handler does, so that other threads can not access the handler while it is already in use from another thread?

For example, I have the following command handler which applies an event, this is within my aggregate class:

@CommandHandler

public BidAggregate(CreateBidCommand command)

{

apply(new BidCreatedEvent(command));

/* My additional code that I want to add for database processing */

}

Here is my event handler, which I have in a component class for all handling:

@EventHandler

public void handle(BidCreatedEvent event) {

logger.debug(“Bid Creation Event: {}”, event.getId());

}

I would rather perform the database operations from within the command handler, as I don’t want to pass through objects, to the event object, as I don’t want that stored in the domainevententry payload. Is this possible and will it lock the way I expect it to?

Thanks,

Robert

Hi Robert,

Axon uses an exclusive lock on an Aggregate instance when it is handling a command. However, this is not a distributed lock, so access to the aggregate is only restricted on the same instance of your application.

Event Handlers use a different mechanism. There, it depends on whether you use a Tracking processor, or a subscribing one. In the case of a Tracking Processor, each event will be handled once by any component. There can be concurrent access, but not for the same event. With a subscribing processor, access is managed by the source of the events. Generally, events are published in the thread that also published the events (i.e. the command handler), meaning events from the same aggregate are always handled sequentially, but events from different aggregate instances may be handled concurrently (even the same events).

Hope this clarifies things.

Cheers,

Allard

Thanks Allard,

By default, is it a tracking or subscribing processor that is used for the Event Handler?

Axon 3: Subscribing
Axon 4: Tracking

thanks!

While a specific aggregate is being utilized in the CommandHandler, can another utilize the same aggregate (I would hope this is no).

Essentially, if a command is dispatched, as so:

commandBus.dispatch(GenericCommandMessage.asCommandMessage(new ValidDeleteBidCommand(demandbids.get(0),“Delete all bids”)));

the aggregate as, say “123-my-aggregate”.

Until the command handling is completed, there should not be the possibility of another command being processed with the given aggregate, no matter the command…is this correct?

Thanks!

I believe Allard’s initial response is the answer to this question.

Right, I’m just verifying I understood what he said correctly.

Essentially, for the given, running application, the behavior is that command handling will be locked for that aggregate until it is released and available for utilization by the next thread.

We would only have one instance of the application running, that can be utilized by various clients – not a multi-application solution hitting the same database.

Hi Robert,

you understood correctly ;-). Locks happen on the aggregate level, so a single aggregate instance will not be invoked concurrently and each command will execute on the state left by the previous one.

Cheers,

Allard

Allard, is there any additional configuration required within the Event Handler for the subscribing processors to work effectively? We’re currently utilizing Axon 3.3, so we have the default subscribing processors in place.

Essentially, if we kicked off two instances of the application and sent events against the same database, for the same aggregate value - would locking be handled (seems like it queues the events sequentially and processes them in the order they came in).

The reason I ask is because I see this section in your documentation related to tracking processors:

Also, do I require a distributed command bus for what I’m trying to do? Multiple instances of the same application, which ultimately feed to the same event store and database (a single postgreSQL instance)

I am currently using the default command bus provided out of the box by Axon.

So essentially, I need to know if I can use the subscribing processor, configured by default by Axon (for a distributed solution) and also if I require a distributed command bus in order to get the functionality that I require.

We want locking to happen for aggregates, specifically, not by event (so tracking processors would not work for our use case)

In the end, I want to make sure I can have these separate clients issuing the same commands and locking appropriately on the event handler, when the same aggregate is utilized, where I will perform all database operations.

Thanks and sorry for all the questions!

Sorry for the continued brain dump on this thread, but I’ve been reading through other posts trying to confidently come up with the correct solution to my desired implementation. I’m not sure I really need a distributed command bus, if the event handling mechanism is properly locking per aggregate, even across a distributed application (multiple instances of the same application, executing against a single database).

I read this response from Allard in another post:

subscribing processors have no control over which node received which event. They just register a handler and are at the mercy of the delivery mechanism.

We do have some ideas (not very concrete yet) to also have AxonServer coordinate sending events to Subscribing processors across nodes. However, there are some challenges regarding guaranteed delivery which are much more elegantly solved with Tracking processors.

It is much more likely that we’ll introduce a retention period for data, in case events are not required for event sourcing.

For our implementation, it is not a problem if we are “at the mercy of the delivery mechanism” so long as the database is being locked properly, per unique aggregate on event, and not allowing concurrent operations for the same given aggregate ID.

Essentially, I don’t want an event handler to start executing data changes to my postgreSQL database if the same event is called on another instance of the application, with the same aggregate, and it is currently being processed on that node in my distributed node solution.

Is this functionality provided out of the box, for a subscribing processor?

Hi Robert,

Completely fair to drop a brain dump here if you’d ask me.
It might be a little tough to digest for readers, but it does provide a fair source to come to your ending question here. :wink:

I can however be very short with answering your question.
No, there is no mechanism in place to enforce delegation of events to a Subscribing Event Processor.

As the comment you’ve dug up from Allard points out, the Subscribing Event Processor do not have control from what node they receive events.
A Subscribing Event Processor will receive events from what we’ve called a SubscribingMessageSource.
In a default set up, the EventBus will be the SubscribingMessageSource for your processors.

Due to this, it will only receive events which have been published within that node of your application.

If you thus have your application scaled out (for fault tolerance reasons for example), events which occur on Node 1 will only be handled by Subscribing Event Processors on Node 1.
Logically, this thus also holds for events published under Node 2; they’ll only be handled by the Subscribing Event Processors on Node 2.

By far the simplest solution to enforce the desired coordination you’re looking for, is to use Tracking Event Processor.
Another thing you could do, is pretty tightly coupled to the fact that you want a given Subscribing Event Processor to control an Aggregate instance it’s events.
If you ensure the commands for every single Aggregate instance are handled by the same node, always, then you’re ensured that the given node will be the originating point of the Events for that Aggregate.
You’d thus effectively ensure that only that Node’s Subscribing Event Processor will receives the events for that Aggregate.

Although this works in theory, you will not be covered in the scenario that one of your nodes dies, as the command message routing would then be changed over.

Concluding, I’d try to start using Tracking Event Processor.
All this explaining here is again a pointer for me personally that changing over the default from subscribing to tracking for Axon 4 was a good decision; it just helps with dedicated routing.

Hope this sheds some light on your situation Robert.

Cheers,
Steven

So, essentially - there currently really is no good way to have subscribing processor functionality in a distributed solution?

I understand the tracking processor locks by event, not by aggregate. While the subscribing processor allows the same event to be processed, so long as it is not using the same aggregate.

We really wish to have an event which can be processed in parallel, so long as the aggregate is not the same – a tracking processor would not give us this desired functionality.

Is it possible to perform all our database alteration operations from within the command handlers in the aggregate root – utilizing a distributed command bus?

I feel this would ensure we are not locking on the same aggregate, while a command is being handled for that given aggregate ID.

Thoughts, would this work?

I really appreciate your response to my brain dump!!!

Hi Robert,

As pointed out in my response, if you ensure that the distributed command bus will route all commands for a given aggregate to the same instance consistently, then yes, you’ve effectively solved your problem too.

However, as also pointed out, this is far from an ideal situation, as in a distributed system you should be able to deal with failing nodes.
A failing node will mean the consistent routing fails to.

It would be a lot better if your Query Models do not rely on the successful handling of a given command.
A command is successfully handled if the Aggregate has decided so.

If you let a failure in updating your Query Model influence that, you’ve effectively coupled your Command and Query model again; you’d thus not be doing CQRS in this situation.
Your Query Model can always be recreated if you’d be using Tracking Event Processors, as you can simply replay the events against it, whenever you’d want.
A failure in updating your models due to some bug in the code can thus be solved by (1) solving the bug and (2) replaying the events for the given Tracking Event Processor backing your Query Model.

From the angle you’re taking I do feel that that’s what you’re doing at the moment, hence my emphasize on the above points.
Thus, again, I’d suggest to start using Tracking Event Processor to end up with a more fool proof application.

Cheers,
Steven

You’re absolutely right – that is what we are currently doing, although our solution would be incredibly optimized by being able to lock per aggregate, rather than by specific event.

We’ll have to discuss this matter amongst our team and see if it’s even a viable solution for us to lock on events, rather than aggregates. I’m worried it will significantly affect our performance to require the event to be locked while another thread wishes to utilize the same event for a different aggregate.

I’ve read in other posts you’ve made on this User group, related to handling all database alteration operations from within the event handler to ensure CQRS – and I want to get our solution to follow that model.

Hi Robert,

Discussing with your team the right approach for your situation is obviously the most important thing to do in this scenario.
If you all decide that the current approach is the way to go, who’s to argue with you, the subject matter experts, that something should be the other way around?

I hope I haven’t been to pushy in my earlier responses, if so I’d like to apologies apologize.

If you might have any future questions on how to approach these topics, feel free to reach out on this user group.
Do know that we also provide in depth discussion on this topic, on site, if desired.

Regardless, I hope these insights help you and your team out Robert!

Cheers,
Steven

Not too pushy, at all, Steven – I greatly appreciate the direct answers. In the end, we want the correct solution and that’s why I’m here looking for your insight.

I’ve shared my findings and your input with the team – and I agree with your proposal, from the perspective of implementation time and overall functionality that we desire.

I think we may be able to alter our approach to Tracking Processors, based on performance tests that we have already ran, I just need buy in from the team :smiley:

Thanks!