Command and control API uses address control/${tenant_id}/${reply_id} for receiving responses in consumer applications. Users are free to choose ${reply_id}. If an application wants to receive all responses of one tenant, hono docs recommend to use an arbitrary (short) string as ${reply_id} without ${device_id} and to keep the receiver link open.
However, protocol adapters use a very similar addressing scheme to receive commands from applications in the form of control/${tenant_id}/${device_id}. If ${device_id} == ${reply_id} we now have two competing receiver links and messaging network can not distinguish if a message should be sent to protocol adapter or to the application.
One possible solution would be to change addressing scheme for responses to
response/${tenant_id}/${reply_id}. Of course this would require an API change.
WDYT?
I would like to see the "control" keyword in the address.
Therefore, I think we could define as address schemes:
control/request/${tenant_id}/${device_id} for the application to send commands on.
control/response/${tenant_id}/${reply_id} for the application to receive replies on.
Thinking about the necessary permissions for such addresses in EnMasse/Qpid/Keycloak, these Keycloak groups would have to be assigned to the user:
send_control/request/${tenant_id}
recv_control/response/${tenant_id}
All addresses in Hono are built around the assumption that the first segment represents the endpoint, the second segment indicates the tenant and the third segment indicates the device ID. If we want to diverge from this pattern in the C&C API then we will have a lot of work to do, introducing special cases all over Hono. I'd rather not do that, so introducing an additional path segment in the addresses is not an option FMPOV.
What about something like this:
control_request/${tenant_id}/${device_id}
control_response/${tenant_id}/${reply_id}
?
I think we should wait for the results of the discussion around #930 as it might have an impact on the addressing scheme used for C&C as well.
As the discussion for #930 is mostly done, I think we can define the address patterns here now.
I would be ok with the last mentioned suggestion:
control_request/${tenant_id}/${device_id}
control_response/${tenant_id}/${reply_id}
Sender link for the command requests would be on control_request/${tenant_id}.
For the potential additional message transfer as shown in #930 (regarding routing of commands mapped to gateways), I would suggest:
control_request_internal/${tenant_id}/${device_id}
@calohmn this means that the protocol adapters open a command receiver link on source address
control_request_internal/${tenant_id}/${device_id}
for each device that wants to receive commands, instead of the currently used
control/${tenant_id}/${device_id}
right?
@sophokles73 yes.
Here's how I would suggest introducing these changes:
control_request/${tenant_id} endpoint and the provided command client classes will use that too.control/${tenant_id}/${device_id} endpoint will still work, but will lack the gateway-mapping feature.control_response/${tenant_id}/${reply_id} as command response receiver address. The existing control/${tenant_id}/${reply_id} address shall still work as well. [1]control/${tenant_id}/${device_id} endpoint for sending commands and the control/${tenant_id}/${reply_id} endpoint for receiving command responses.control/${tenant_id}/${device_id} to control_request_internal/${tenant_id}/${device_id}.control_request_internal addresses then.control/${tenant_id}/${reply_id} an invalid address; only control_response/${tenant_id}/${reply_id} shall be used.[1] Supporting both response address styles will require some changes in the current implementation (e.g. also in the CommandConsumerFactory interface). Things would be easier if we could switch from the old to the new pattern in one go. But then there would be no smooth migration path.
@sophokles73, @ctron comments on the above?
@calohmn I wonder why supporting the old reply address would require changes in CommandConsumerFactory? FMPOV the client classes we provide already only use the new addresses, both for sending commands as well as for receiving responses. However, we still support control/${tenant_id}/${device_id} for sending commands on the dispatch router so if an application uses the old address. If an application uses a reply-to address of the form control/${tenant_id}/${reply_id} so be it. My understanding is that the protocol adapters forward the response to the dispatch router using whatever address has been specified in the command response, or am I mistaken?
I wonder why supporting the old reply address would require changes in
CommandConsumerFactory?
That was just my initial assumption when seeing that the getCommandResponseSender method creates a CommandResponseSender that will always prepend a fixed prefix ("control" or soon "control_response") to the replyToId address part when sending the command response back to the application.
But upon closer inspection that looks unnecessary. I now want to encode the info about the "control" prefix being used in the reply address in the bit that is already added to the Command requestId and replyToId in order to mark the removeDeviceFromReplyTo option (see Command#getRequestId).
Using that info, the CommandResponseSender will then prepend the appropriate control or control_response prefix.
@sophokles73 Actually, there is a change to the CommandConsumerFactory interface needed:
The command response sender link with either the "control" or "control_response" address prefix is created via the getCommandResponseSender method. From its parameters tenantId and replyId the decision between whether to use "control" or "control_response" can't be made. In the invoking method, this information is available however.
Therefore I would add a new getLegacyCommandResponseSender method to the CommandConsumerFactory interface. I'm currently preparing a PR with this.
As suggested by @sophokles73, a solution that is easier to implement would be to keep the command response address pattern the same ("control"). For the command requests, the "command" prefix (instead of "control_request") will be newly introduced.
The changes would then be:
command/${tenant_id} endpoint for sending commands (with gateway-mapping feature).control/${tenant_id}/${device_id} endpoint for sending commands will still work, but will lack the gateway-mapping feature. It will be marked as deprecated.control/${tenant_id}/${reply_id} address for the command responses stays the same.control/${tenant_id}/${device_id} to control_request_internal/${tenant_id}/${device_id}. Only Protocol Adapter users shall get access to control_request_internal addresses then.command/${tenant_id} as endpoint for sending a command,control/${tenant_id}/${reply_id} for receiving command response(s).The disadvantage of the above easier-to-implement solution would be a somewhat inconsistent naming scheme: Only the Downstream Application sender link has the command prefix. Downstream Application receiver link as well as device subscription address and device command response address all have the control prefix.
If we want to stick with using a the new command prefix instead of control, we could
Option A:
command endpoints for the device command subscription addresses and command response addressescommand/${tenant_id} for sending commandscommand_response/${tenant_id}/${reply_id} for receiving command responsescontrol endpoints and remove them at some pointThis would of course mean that all existing Hono devices have to change their command subscription addresses at some point, which could mean quite some effort. All in all a bigger change than just changing the downstream-application-facing endpoints, possibly not worth the benefit of having a somewhat better fitting name.
Sticking with the "control" prefix, there is still the original proposal from above:
Option B:
control_request/${tenant_id} for sending commandscontrol_response/${tenant_id}/${reply_id} for receiving command responsescontrol/${tenant_id}/${device_id} and control/${tenant_id}/${reply_id} endpoints and remove them at some pointOption B2:
control/${tenant_id} instead of control_request/${tenant_id} for sending commands.As to an option that doesn't introduce the extra CommandConsumerFactory legacy method (as shown in #1237), we would have to keep the control command response receiver link prefix and use a command sender link prefix other than that. I don't see a good naming solution with that though.
@sophokles73, @dejanb, @ctron Any preference regarding the options above? Should we do the renaming from control to command?
As discussed with @sophokles73, we would put the implementation of this in a Hono 1.0 M5 milestone (not M4).
Command would actually be command and not control. That is somewhat confusing for people at the moment.command_request and command_response).response instead of command_response). I think for the command & control addresses we see more frames on the wire that actually contain the name of the addresses.My proposal would be to use command/${tenant_id} and response/${tenant_id}/${reply_id}.
And maybe think about shrinking this down to the short versions, which we already defined for some addresses: c/${tenant_id}/${reply_id} and r/${tenant_id}/${reply_id}.
@ctron wrote
I would also prefer it to be explicit in naming (so command_request and command_response).
and then
My proposal would be to use command/${tenant_id} and response/${tenant_id}/${reply_id}.
Not sure if I understand correctly what you actually prefer. Is it just command or command_request?
Regardless of what we chose as the new endpoint name(s), we will need to keep the existing endpoints for some time.
That said, I also like using command (and its short version c) for sending commands to devices.
However, I am a little concerned that using just response as the endpoint for sending and receiving response messages in reply to the commands might be a little too generic.We might have other types of response messages going through the system in the future and I would rather be a little more specific here in order to prevent naming clashes and confusion later on.
I therefore would propose to use command_response (and its short version cr) for sending and receiving the response messages.
@ctron wrote
I would also prefer it to be explicit in naming (so command_request and command_response).
and then
My proposal would be to use command/${tenant_id} and response/${tenant_id}/${reply_id}.
Not sure if I understand correctly what you actually prefer. Is it just
commandorcommand_request?
I would prefer command_request. But on the other hand, that is quite long. And so, altough preferring the longer, more explicit version, I would still recommend to use command. Maybe someone has an idea to achieve both.
And so, altough preferring the longer, more explicit version, I would still recommend to use command. Maybe someone has an idea to achieve both.
Just command for the request would be fine with me.
So, to sum it up, choosing command_response over just using response (which I also find too generic), we would end up with option A from above
Option A:
- Add additional
commandendpoints for the device command subscription addresses and command response addresses- let the downstream application use
command/${tenant_id}for sending commands- let the downstream application use
command_response/${tenant_id}/${reply_id}for receiving command responses- deprecate all the
controlendpoints and remove them at some point
Add additional command endpoints for the device command subscription addresses and command response addresses
not sure but I think that should be:
Add additional
commandendpoint for the device command subscription addresses and additionalcommand_responseendpoint for sending responses (to commands)
@sophokles73 Yes, however that would apply only for the AMQP adapter endpoint.
For HTTP and MQTT adapters, we would just add new command endpoints:
HTTP command response: /command/res/${commandRequestId}
MQTT command response: command///res/${req-id}/${status}
@DanielMaier-BSI can we (i.e. you) close this issue now that the north bound endpoint prefix for command responses has been changed?