Connectivity
All deepstream SDKs establish a persistent, bidirectional connection to the platform. This connection can be lost due to network outage, lack of mobile network coverage or similar problems β if this happens all SDKs will queue outgoing updates and try to re-establish the connection.
Reconnection behaviourβ
If a connection is lost, the client will immediately attempt to reconnect. Should that fail, it will wait a certain time and retry. Upon every unsuccessful attempt it will increment the time until the next attempt is made by a number of milliseconds specified in reconnectIntervalIncrement
. For example if this is set to 2000
the first reconnection attempt will be made immediately, the second after two seconds, the next four seconds after that and so on. You can specify an upper limit to this as maxReconnectInterval
. After a number of unsuccessful attempts configurable as maxReconnectAttempts
the client will give up and change the connection-state to ERROR
.
Heartbeatsβ
Even if your connection is established, messages might not arrive. To check this, clients continuously send small ping-messages to the platform to make sure itβs still reachable. If the client misses two consecutive responses it will change the connection-state to ERROR
regardless of connectivity. You can configure how frequently these heartbeat messages are sent via heartbeatInterval
(every 30 seconds by default).
Connection Statesβ
Each SDK provides the current connection-state as well as a way to listen for changes.
Connected
OPENβ
The connection is established; everything is fine.
Not Connected
RECONNECTINGβ
The connection was lost to server. The client makes reconnection attempts.
CLOSEDβ
The connection was deliberately closed by the user via client.close()
. No reconnection attempts will be made. The client also starts in this state, but almost immediatly switches to AWAITING_CONNECTION
.
ERRORβ
The connection is finally declared unrecoverable, e.g. as a result from too many failed reconnection attempts or missed heartbeats. No further reconnection attempts will be made.
OFFLINEβ
The client deliberately disconnected from the server using the pause()
method. Can be reconnected using the resume()
method.
Intermediate States
AWAITING_CONNECTIONβ
The client has established the physical connection and waits for the initial response from the server.
CHALLENGINGβ
The client is currently undergoing a negotiation sequence that might result in a redirect or exchange of configuration.
AWAITING_AUTHENTICATIONβ
State after the client was initialised, but before .login()
was called.
AUTHENTICATINGβ
State after .login()
was called, but before the response from the platform is received.
An Exampleβ
const options = {
// Reconnect after 10, 20 and 30 seconds
reconnectIntervalIncrement: 10000,
// Try reconnecting every thirty seconds
maxReconnectInterval: 30000,
// We never want to stop trying to reconnect
maxReconnectAttempts: Infinity,
// Send heartbeats only once a minute
heartbeatInterval: 60000
};
const client = new DeepstreamClient('<url>', options)
client.login()
// Assume we're updating a green/yellow/red indicator for connectionState with jQuery
const connectionStateIndicator = $('#connection-state-indicator');
client.on('connectionStateChanged', connectionState => {
connectionStateIndicator.removeClass('good neutral bad')
switch (connectionState) {
case 'OPEN':
connectionStateIndicator.addClass('good')
break
case 'CLOSED':
case 'ERROR':
connectionStateIndicator.addClass('bad')
break
default:
connectionStateIndicator.addClass('neutral')
}
})
Closed client connectionβ
Once the client closes the connection to the server calling the close()
method, it can not be opened again using the same instance of the client. This can cause some issues on web/mobile when we logout a user, and close it's deepstream client connection, and then try to login as a new user. It will not be possible using the same instance of the client. One solution is to use the singleton pattern, as shown in this quick example:
// Deepstream client using "singleton" pattern
let client = null
const dsClient = () => {
if (!client) {
client = new DeepstreamClient('<url>', options)
}
if (client && client.getConnectionState() === 'CLOSED') {
client = new DeepstreamClient('<url>', options)
}
return client
}
Then pass along and call the dsClient function for interacting with the client methods:
dsClient().login()
dsClient().record.getRecord(recordName)
Using this pattern, if the client connection is closed, a new one will be instantiated and returned.