Command architecture for long lived commands

Newbie question again.

I have as part of my app lots of file downloads and especially on the fly zipped files with LARGE files (over 500Mb/file, and zipped files can contain multiple files). Today I redirect to a special download microservice that only handles the downloads in a separate request and then sends a downloaded message on SQS.

How is the command bus implemented when it comes to threads? Would it be possible/advicable to do the downloads in a command handler instead? This could help make the app little more consistent. I could then easily process the download in the command handler and then emitt events when files are being added to the zip file… I do not want this to block the whole commandbus though…

Any pointers?
Cheers
Fredrik

Hmm, and is it possible at all to send along the response into the command? Or is this completely wrong thinking from my side?

I’d try to keep command processing time to a minimum, just validating the business rules for accepting the command and then coordinate any processing/fulfilment of long-running tasks using a saga (https://docs.axoniq.io/reference-guide/1.2-domain-logic/sagas).

Cheers,
Faik

Hi Fredrik, Faik,

Fredrik, typically, your command handlers are set on Aggregates.
What Axon does when it loads an Aggregate from the repository, is to place a lock on it. Hence, if you’d send an Aggregate a ‘DownloadThisCommand’, it will lock the Aggregate for handling other commands until it has finished it’s operation. This, to me, sounds a little off, having an Aggregate download stuff, but then again, I am not familiar with your domain at all.

What I will recommend though is to move away from the default SimpleCommandBus, as command handling will block this bus from receiving other commands.
Instead, you can use the AsynchronousCommandBus, which will create separate threads for publishing and handling the commands.
Additionally, from the small domain-portion I get from your description, I think I’d put such a command handler on a singleton rather than on an aggregate.

You can also take the route Faik is suggestion. So, have a saga perform the download and send compensating action if it fails.
This could be a valid use case, but this depends on what you’re actually trying to do here.

When you’d offload the downloading process to the saga however, I think your message would look something like ‘RequestToDownloadCommand’ —in-aggregate—> ‘DownloadRequestedEvent’ —in-saga—> ‘Actual-Download’. The ‘…RequestedEvents’ are typically a suggestion the modelling process is taking some weird turns, hence why I wasn’t starting of with a Saga/Event Handler explanation for this.

Hope this helps you out.

Cheers
Steven