Loss of connectivity

Oct 14, 2010 at 3:34 PM
Edited Oct 14, 2010 at 3:55 PM

I am building an online game and chat server with silverlight clients.
The game logic needs to be sure that all the messages are delivered, even in case of short loss of connectivity.

 I like to add some of this functionality. The general idea is:

(1) Messages are uniquely identified within the topic with a progressive integer value (messageId)
(2) The client maintains the last messageId received from each topic. When the client receive a message compare its messageId with the last identifier received
(3) If the messageId has not the expected value (some message is missing), the client discards the message and send a request to the server with the last messageId received correctly
(4) the server send to the client the messages starting from the requested identifier plus one

For the requests in (3) we can create a new OperationContract or we can use the Publish with a special topicId used only for infrastructure messages.
Or the client can issue a Subscribe OperationContract with the same topicId and the last messageId received correctly plus one.
The client can also send several requests in order to sincronize every active topic.

I don’t know if maybe would be better to have two different messageId, one general and another by topic, or have only the identifier by topic (moving the definition int maxMessageId from class InMemoryPubSubBackend to class PublishedTopic) …

That do you think about? 

Thanks, Cristian

Oct 15, 2010 at 7:14 AM

Cristian,

the approach you descrie is in fact very similar to the approach implemented in Laharsub. Check out the design of the protocol at http://laharsub.codeplex.com/wikipage?title=Architecture%20and%20design. One subscribes to a topic using the SubscribeAsync method of the PubSubClient class:

public void SubscribeAsync(Subscription subscription)

The Subscription class identifies not only the topic, but also a numeric identifier of the message within this topic the client would like to start receivng messages from; the server guarantees that messages published to a topic are assigned ever increasing identifiers (but not necessarily consecutive integers):

    public class Subscription
    {
        public int TopicId { get; set; }
        public int From { get; set; }
        public Action<Subscription, Exception> OnError { get; set; }
        public Action<Subscription, PubsubMessage> OnMessageReceived { get; set; }
    }

The OnMessageReceived callback specified in the subscription is invoked whenever a message from the server arrives on the client. The PubsubMessage class specifies the identifier of that particular message:

    public class PubsubMessage
    {
        public int TopicId { get; set; }
        public int MessageId { get; set; }
        public string ContentType { get; set; }
        public Stream Body { get; set; }




//...
}

Should the client ever loose connectivity with the server, the client can re-subscribe to the same topic starting from the last message it successfuly processed from the server.

I belive the pattern above is an answer to your reliability concern.

Thanks,
Tomek

Oct 18, 2010 at 9:59 AM

Tomek,

I am not sure if it is possible that some messages sent by the server to the client can get lost.
If some messages got lost, how can the client know that it is necessary to ask the server to re-send these messages?
I think that if the messageId is assigned to in consecutive integers within a topic, the client has a simple way to know if some messages are missing.

Thanks, Cristian

Oct 18, 2010 at 10:31 PM

Cristian,

It is possible that some messages the Laharsub client requested will not be delivered to the client due to communication failure, but the protocol is organized such that the client will always have a way to determine which message to request from the server next after such failure to avoid missing out on any one of them.

Each HTTP long poll request the client issues to the server specifies the next sequence number of a message within a topic starting from which it is interested in receiving messages. Every response to such request will contain one or more consecutive messages published to the topic, starting from the least sequence number greater or equal the sequence number the client requested.  Each of these messages comes with an integer MessageId value assigned in an increasing order. The HTTP response will always be delivered to the client in its entirety, not at all, or only containing some leading bytes of the response the server generated; the content of the HTTP response is guranteed not to be reordered by the underlying TCP protocol. Given that, in case of a failed delivery or a partial delivery of the HTTP response, the client only needs to note the MessageId of the last message it received in its entirety (N), and issue a new HTTP request to the server asking for messages starting from N+1.

Thanks,
Tomek

Oct 31, 2010 at 9:38 PM

Tomek,

Are you saying that the client can rely on the connection closed event to detect the possibility of missing information and restart the request?

Nov 1, 2010 at 12:48 AM
Edited Nov 1, 2010 at 1:06 AM

Phil,

yes, I am suggesting that when an http long poll fails on the client side (which I think is what you refer to as "connection closed"), the client can request the server to start sending messages beginning from the one the client successfuly received last, since messages are assigned unique and increasing identity numbers.

Thanks,
Tomek