Hi, I want to implement automatic reconnect for a request-reply channel built with asyncio. The challenge here (in contrast to what was discussed before) is, that the server is stateful and needs to detect if a client reconnects.
Before I discuss my ideas and questions, I’d like to briefly explain the channel’s architecture (source code <https://bitbucket.org/ssc/aiomas/src/tip/aiomas/channel.py>): The UI is a Channel object that a client creates when it connects to a server and that a server creates for each new connection. A client sends a request to the server and waits for a reply with rep = await channel.send('ohai') The server side channel waits for requests and replies to them with req = await channel.recv() req.reply('cya') => Complete example <https://bitbucket.org/snippets/ssc/dojx8> The Channel object wraps a ChannelProtocol which is very similar to the built-in asyncio streaming protocol (except that my messages are not "lines" but length-terminated JSON objects). I don’t use custom transport implementations. When a client reconnects, both the client's and the server's channel instances need to stay the same. Creating a new protocol instance (if needed) after a reconnect should be no problem, because it is not exposed to the user. I think the only way for the server to detect if a new client connects or an existing client reconnects is that the client uses some kind of session ID. The server associates a session ID with a channel. And reuses channel instances for known SIDs and creates new channels else. This means that a Channel will always send a greeting message to the server after it successfully connected. It also needs to send a goodby-message when it disconnects on purpose (to tell the server to close the session/channel). Since every message already has a message type (REQUEST, RESULT, EXCEPTION), it wouln’t hurt to add two more types (SESSION_START, SESSION_STOP). So my first question is: Does this sound reasonable? What I described above should work well when the connections drops *before* a request is made or *between* a request and its reply. But what happens if a disconnect happens while a request or reply is being transmitted (after the user called channel.send() but before the server received the complete message). Is there a way to detect this? Or should the client use a timeout and resent the same message (with the same message ID) after a timeout occurs? The server could then decide whether to execute the message (when the original message got lost on the way from the client to the server) or just re-sent its reply (when the reply got lost on its way from the server back to the client). And how could I test this? Its relatively easy to provoke disconnects before a request or between a request and reply, but I have now idea how to break the connection exactly when a message is being transfered. Cheers, Stefan
