Duplication of events caused by a nested invocations of command handlers

Hi,

I’m wondering if anyone can shed some light on why events are duplicated in the following scenario:

CommandA received
CommandHandlerA on AggregateA handles CommandA and calls apply() to apply a new EventA.
CommandHandlerA issues CommandB targeting AggregateA
CommandHandlerB on AggregateA handles CommandB
CommandHandlerB completes
CommandHandlerA completes

The eventsToPulbish property of the DefaultUnitOfWork instance that is committed when CommandHandlerA completes contains two EventA instances. Both instances are the same (ie, the have the same object id).

If I issue a further command from CommandHandlerB for a CommandC, then the eventsToPulbish will contain the same EventA three times.

Is this by design? A bug? Or something wrong with what we’re doing? I’m suspecting the latter. I’m not sure if it’s best practice for a command handler to be issuing a subsequent command to the same aggregate, and perhaps that needs refactoring.

Thanks

Paul

Just a little more detail, it looks like units of work can be nested (NestableUnitOfWork). Both inner and outer units of work contain the event applied by the first command handler. When the outer unit of work is committed, registerScheduledEvents(outerUnitOfWork)
is called which seems to transfer events from the inner to the outer unit of work. In this case, as the inner and outer units of work both reference the same event, the event appears as a duplicate in the outer unit of work and is therefore published twice.

Should events from the unit of work created by one command handler invocation, propagate to nested units of work created when commands are issued from an executing command handler?

Hi Paul,

It might be a bug that causes the event to be duplicated. However, the scenario is also a strange one.
There is no value in an Aggregate sending itself a Command via the command bus. The aggregate can just call a method on itself instead. It saves you time dispatching and loading the aggregate that you already have available anyway.

Cheers,

Allard

Hi Allard,

Many thanks for getting back to me.

Yes, I completely agree. The team had a chat about it and that’s the route we intend to take. The event handler delegated some work to another object instance which had no reference to its caller, but wanted to call back to the caller. I believe the original developers intention was to hook in to Axon’s ability to do this by issuing a command rather than the aggregate passing a reference to itself to the callee. This was most likely to decouple these two objects, so think it was done with the best intentions! I think the belief was Axon would just see the call was already executing in a handler and execute the command as though it was part of the same command execution.

Realising the consequences of doing this has cleared up a number of odd issues we have been seeing.

One of our developers suggested adding a command interceptor that could detect when this happened and throw an exception in case anyone tries to do this again! Perhaps it might be work expanding on this in the docs?

Paul