How to reconnect websocket and subscriptions
When a mobile device goes offline or is sleeping, a websocket connection can be lost and subscriptions can also be lost. This is an attempt to reconnect the websocket.
Context
In an application like the chat we made previously, I need to be able to resume websocket connection when it is closed unexpectedly. This can happen when the device hibernates, when connectivity is lost (3g / 4G...). I also need to subscribe back to channels and notification I was previously subscribed to.
Problem
When a device goes offline of sleeping, the websocket connection can be lost and subscriptions can also be lost.
A way to do it
Store significant events of websocket state
We need to store some specific events when we try to reconstruct websocket connection. We don't want to replay all events (especially business events).
During the lifecycle of the application we will first connect to the websocket, then authenticate to the API through it. Later, we will subscribe to channels (rooms) and notifications.
So I identified types of events
- connected : connected to websocket
- anthenticated : authenticated to API
- subscribedToRoomMessages : listening messages from a specific room
- subscribedToNotifyRoomTyping: listening to /typing event from a specific room
Wrap events
The reconnection engine will store events than need to be replayed in case of deconnection of the websocket. We will add a level of abstraction so that the engin only deals with event playing logic and not websocket technical stuff.
From the technical side, we will listen to events from the engine and do the appropriate behaviour when they occur.
ie. when receiving a connect
event we will run something like websocket.connect()
Play events
When we want to play and event we add it to a play queue. When an event is in the play queue, it is played. Meaning that the actual behaviour is executed (ie. message sent to websocket).
Success
If the callback of the websocket event indicates a succes, the event is unqueued from the play queue and is added/updated in the original event queue.
Failure/timeout
If there is a failure or timeout in callback, the event is replayed until it is a succes or until a try limit is reached. If the limit is reached and error is diplayed to the user indicating that there is a problem.
Reconnect
trigering reconnection
We want to create a "replay engine" to be triggered when the connection from the websocket is lost (error/close ws events). We may want to trigger in regular interval of time or by some event.
Replay events sequentially
Some event have prerequisites (ie. subcribe to room requires authentication to API and authentication required connection). In order to deal with it in a simple way we replay events sequentially. When an event is sucessfully played, the next is played until there is no more events to play in queue.
Replayed event should be flagged as replay
so they are not added to the original sequence of events to play in case of deconnection.
Events in this original sequence should only be added when a new significant event is played (sub to a new room for instance)