How to influence Command to send specified handler?

I have read many docs but the answer could not be found unfortunately . I am trying to build an architecture where many small clients will be connected to the axon server. these small clients are very focused only specified commands, like only Orders with specific IDS should go to specific clients

UpdateOrderCommand (orderId=1) → client 1
ConfirmOrderCommand (orderId=1) → client 1

UpdateOrderCommand (orderId=2) → client 2
ConfirmOrderCommand (orderId=2) → client 2

Can we do that?

Thank you

Hi @m1nd1a, could you expand further on why you have the requirement to have specific instances handle specific aggregate instances for command handling? Out of the box using the AxonServer will load balance and route commands for the same instance of an aggregate to the same command handling client.

Thank you @brunch for your answer. I will try to explain my architecture. There are many Raspberry Pi clients . one user = one Raspberry Pi . They are doing very specific tasks, these users are connected to the central server through mobile apps. They are sending some command to Raspberry Pi and getting some results from them. So that’s why I wanted to run an axon client on Raspberry Pi and get only specific commands. filtered by userId or something like that

You can use tags, but it’s not meant to be so fine-grained. It should work. It does always deliver the command even if there is no match.
I’m not sure about the use case, but since you mention using a Raspberry, you might want to use a local command bus, so some or all the commands aren’t routed via Axon Server?

Thank you @Gerard for your answer, I will try to explain what I need exactly

  1. We sell Raspberrys , these Raspberrys are ready to connect our central server, on the device already installed software and Axon server client
  2. User Bob buys device
  3. Bob register on our platform and attach Rasberry to his profile
  4. Bob send particular task to Rasberry and get result

Question is : When Bob sends some request to server, server translates this request to command, how Can I send this command to a particular client (Raspberry) ?

Thank you

My question is, should all the commands sent by Bob be handled by the Raspberry Bob bought? If that is the case, using a local command bus might be best.

Although I agree with @Gerard that if the command is dispatched and handled by this RaspberryPi “Bob” bought, then there’s no need to distribute the command bus. Hence, you could use a local version, like the SimpleCommandBus or AsynchronousCommandBus.

However, if the command is dispatched from the central server, you would want a distributed command bus solution like Axon Server.

Nonetheless, I think I have sad news for you. Although the tagging feature suggested by @Gerard would help you with ensuring the shortest route is taken when connecting an Axon Framework application with Axon Server, and thus shortening the networking distance of a given message, it does not provide you a means to dispatch a command to a specific instance.

As pointed out by @brunch earlier, Axon Server and Axon Framework ensure a given command handling node is consistently in charge of a specific aggregate’s command handlers.
It does so by using a consistent hashing algorithm for all (Axon Framework) nodes.
Then, when dispatching a command, Axon Framework extracts a “routing value” based on the command (this is provided by the RoutingStrategy, as we described here in our Reference Guide), which will form the uniqueness that ensures commands containing the same routing value all end up at the same node.

This “routing value” represents a spot on the consistent hash ring. All command handling nodes, in turn, “own” a number of spots on the consistent hash ring (called the load factor). These spots are evenly distributed over the hash ring.

With this in place, whenever you dispatch a command, the follow steps occur:

  1. The command is pulled through the RoutingStrategy, resulting in a routing value.
  2. The routing value is added to the command and given to Axon Server.
  3. Axon Server knows of the registered command handlers and finds the right consistent hash ring representing the function that can handle the newly received command.
  4. Upon finding the set, it uses the added routing value to find the earliest match within the consistent hash ring. This match results in the address to route the command to.

As the consistent hash ring has a nearly endless supply of positions, we can add any number of nodes or remove them again, while maintaining the certainty that a command intended for a specific handler and aggregate is routed consistently.

The problem is that you as a user of Axon Framework or Axon Server cannot control which positions of the consistent hash ring go to what instance.

So, jumping back to your example, whenever you would register a Raspberry Pi, that would lead to registering command handlers with the central Axon Server installment. In doing so, the node’s handlers receive a random set of position in the consistent hash ring.

There are two ways how I think you can battle this, both with drawbacks:

  1. Use dedicated contexts per user. By doing so, the connection between Axon Server and Axon Framework would be unique per client. However, this will have massive implications for Axon Server, as it maintains several thread pools per context. Hence, a thread pool set per user would soon explode the amount of resources the system running Axon Server requires.
  2. Register command handlers manually, by adding the user identifier to the command name. This should proof doable, but honestly feels a little hacky. By doing this, you would essentially by pass the consistent hash ring implementation, as the uniqueness now comes from the commandName attribute instead of the “routing value.” The commandName value is normally not something people adjust, as it defaults to the FQCN of the command you dispatch and handle. But, you can adjust the commandName when subscribing handlers with the CommandBus and could do the same when dispatching a command by constructing the CommandMessage manually. The dispatching pointer is rather straightforward, but the command handler subscription pointer isn’t. It would force you to not use Axon Framework’s automated command handler registration through the annotations.

Long answer short. You could achieve specific routing towards an exact Axon Framework instance, but it isn’t built to support this cleanly.
However, it does again merit the question raised earlier: why?
Why would the Raspberry Pi your clients receive need to be an Axon Framework application that guards the user’s consistency boundary at all?

Thank you for all your comments and effort . these comments help me a lot