This is a very generic question not much related to any language/protocol.
I have a desktop application and a backend that communicate via TCP. Most protocol events are paired -- request/response. For example, I say "I want to create a secret chat with a person_id" (CreateChatRequest
), and the backend replies with "Ok, I have created one for you" (CreateChatResponse
).
Some of the backend developers say that the client must properly handle the CreateChatResponse
even if no CreateChatRequest
was issued by the client. They call it flexibility. While I don't find this approach valid at all. In my opinion, there must be some new protocol event like RequestToCreateChatOnBehalfOfTheClient
that can be issued by the backend any time they want and I will handle it in a very simple way -- send the CreateChatRequest
as if a user would do it themselves.
Is there any book/specification that says which approach is better? Or is there no "better" approach and it all depends on how we agree on the protocol? Though I am pretty sure there must be some best practices on the protocol development and responses from the backend should not be issued spontaneously.
UPDATE:
Maybe my initial post was too vague, so I'll clarify. Whenever I initiate CreateChatRequest
from the client, I usually do some setup (e.g. create a widget for this chat). I do always listen for CreateChatResponse
s and when I receive it I check if I have a widget that I can map this CreateChatResponse
to. The CreateChatResponse
for which there was no CreateChatRequest
is simply ignored.
Also, we have a bunch of events that the server sends without a request (there are no protocol events for requesting this at all). They are simply named differently, let's say FromServer_YourProfile
that I always receive only once post-login.
The "chat" here is just an example, no need to think about some real chat that may include other participants. The overall idea is that we have let's say 100+ features that work in a Request->Response
manner. And sometimes the Product/Marketing teams come up with ideas like "can we do this/that without a client change" and the backend team thinks that they can send a SOMETHINGResponse
and the client will react properly. When the client does not do it they call it a bug. Likely I could have developed the client-side architecture in a way that SOMETHINGRequest
only sends a protocol event to the server and the entire logic is put in the SOMETHINGResponse
handler. Thus, the behavior would be more server-driven but due to network latencies I usually have to do some UI stuff immediately after/before sending the SOMETHINGRequest
, thus we get back to the mapping approach, where the received SOMETHINGResponse
must be mapped to the initial SOMETHINGRequest
, which in turn makes supporting the unsolicited SOMETHINGResponse
tricky again.
Looks like there are the following options:
- Whenever you develop a protocol event pair (
SOMETHINGRequest->SOMETHINGResponse
) you must explicitly agree on if theSOMETHINGResponse
may arrive spontaneously without a client request. - Whenever you develop a protocol event pair (
SOMETHINGRequest->SOMETHINGResponse
) you must always consider unsolicitedSOMETHINGResponse
arrival. - In the
SOMETHINGRequest->SOMETHINGResponse
design the response must not arrive without a request. If you want the server to emulate the request from the client there must be a separate newFromServer_PleaseDoSomething
event. - There are no best practices on this, just do whatever works for you.
2 Answers 2
I would say it depends on the functional requirements more than anything else, but also what you mean by "properly handle".
If a chat can only be opened on the client after a client request (like hitting the "new chat" button), then it does not make sense to accept unsolicited create chat response. In this case "properly handling" then response is ignoring it, at least no crash.
If the backend server can open chat on the client without the client having requesting one, then "properly handling" the response is to accept is as if a request was performed.
... the client must properly handle the CreateChatResponse even if no CreateChatRequest was issued by the client. They call it flexibility.
It has very little to do with "flexibility".
It has more to do with the nature of asynchronous messaging between client and server.
Just because the last thing the client sent to the server was a CreateChatRequest, doesn't mean that a CreateChatResponse will be the next thing received by the client. In a busy, multi-threaded system, it's entirely feasible that the client might see an exchange like this:
Send: Put_The_Coffee_On_Request
Send: Send CreateChat_Request
Receive: HTTP418_Im_A_Teapot_Response
Receive: CreateChat_Response
The two Conversations become interlaced and the client, somehow, has to make sense of this. If the client has a single "hub" that receives all messages, then this handling stuff out of sequence is not just desirable but practically essential. This may be what the "back-end" developers, who work in exactly this way, are talking about.
For reference: RFC2324 Hyper Text Coffee Pot Control Protocol
-
1Figuring out which response belongs to which request is the responsibility of the client and how all asynchronous systems work. But that is not relevant for OP's question, as it is not the same as having the ability to receive responses to requests you never even sent or knew of - which is what OP is being asked to implement. Take your example and just remove
Send CreateChat_Request
from it. Does the response still make sense when there is no related request?Flater– Flater01/26/2021 13:47:11Commented Jan 26, 2021 at 13:47
CreateChatRequest
event was issued? So why should it be a problem to ignore such unexpected events? Please clarify.CreateChatResponse
message apart from a response to a request? You will have to consider message-crossing scenarios like where the client sends a request and then receives an unsolicitedCreateChatResponse
relating to a different chat.CreateChatRequest
, and I receive aCreateChatResponse
. What about you, the person who did not create a chat, but is now part of the chat that I opened? What I'm suspecting here is that the backend is designed to send the sameCreateChatResponse
to you, because you are a participant in a created chat - even though you were not the one who created the chat. It might use aCreateChatResponse
as the trigger to open a chat (on both ends). If this is how the backend works, the backend team's advice makes sense.