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

Reply via email to