Hi Sam, Gideon,
I’d like to add that you should take the stance to perform zero blocking operations from within an Aggregate.
Yes, the framework is set up so that you can wire virtually anything in your message handling functions (through Parameter Resolvers), but not any service is suitable to wired in an Aggregate.
When you dispatch a command, the framework will always place a lock on that exact Aggregate instance (through the LockingRepository).
This is done to ensure no concurrent operations occur on a single Aggregate, which is desirable from a consistency constraints perspective.
Added, 9 out of 10 times a Command is directed towards a single Aggregate as well.
Thus, if you’d wire a
CommandBus in an Aggregate to dispatch another command, you will not lock one Aggregate, but two Aggregates.
Additionally, if that new command you dispatch circles back to the Aggregate instances which dispatched, you’re even in bigger sh*t.
Now let me circle back to my zero blocking operations argument.
The fact your Aggregate is locked is why I state you should not perform any blocking operations from within an Aggregate.
Doing so, will only extend the period of the lock, decrease the number of operations you could perform on an Aggregate within a given time frame.
This can thus greatly slow down your entire system (trust me, I’ve been there).
So, Sam, I’d take Gideon’s guidance on this.
Segregate the concerns and let your Aggregate solely deal with it’s own consistency boundary.
If you want to deal with dispatching follow up commands as a reaction to certain events, then that logic should be placed in a different component (e.g. a Saga or regular Event Handling Component).
It is not the responsibility of your Aggregate to communicate with other Aggregates through commands.
Hope this helps you out Sam.