Connection Management
Keepalive
The server closes a WebSocket connection it has received nothing from for 120
seconds, announcing it with connection.closing and reason timeout.
Connections through a transport adapter follow their own protocol's keepalive
instead. Anything counts:
a request, connection.ping or a WebSocket ping frame. A client with nothing to
send sends one of the last two at least every 60 seconds. Native ping frames are
the cheaper choice; browsers cannot send them and use connection.ping.
Ping
Checks the connection at application level and keeps it alive, for clients that cannot send WebSocket ping frames.
Request:
{"type": "connection.ping"}
Control reply:
{"type": "connection.pong"}
Disconnect
The client can send connection.close to gracefully close the session.
Request:
{"type": "connection.close"}
Response:
{"type": "connection.close", "ok": true}
After queuing this response, the server closes the underlying connection.
Server may also initiate disconnect:
{
"type": "connection.closing",
"data": {
"reason": "timeout",
"message": "No activity for 120 seconds"
}
}
Reason values:
timeout— Client inactivity timeoutmaintenance— Server maintenancerestart— Server restart
Passive Connections
A connection is active while somebody is looking at the client, and passive while the client works unseen — a page in a background tab, or an app syncing in the background after a push woke it. A passive connection:
- keeps its user online, as any open connection does, but not active: contacts see when somebody last looked;
- does not stop pushes to its session;
- cannot do what needs a person present:
typing.setis dropped, and creating a direct transfer returnsinvalid_state; - otherwise works as usual: it receives every event, and may send messages — a reply typed into a notification — or accept a direct transfer, as a notification's button does, without making its user active.
A connection is active unless the client says otherwise; one through a
transport adapter always is, since its protocol has no such notion. A
background sync passes "active": false in
connection.hello, so that it never counts as somebody
looking, not even for a moment: the device keeps getting its pushes, and its
user does not flash active. activity.set switches an open connection when the
client comes to the foreground or leaves it:
{"id":"act-1","type":"activity.set","data":{"active":false}}
{"id":"act-1","type":"activity.set","ok":true}
Turning the user's last active connection passive sends contacts
presence.updated with the user no longer active, once the
grace has passed with nobody looking again, so that a
switch between apps tells them nothing. Turning one active sends
presence.updated at once. Neither changes whether the user is online, nor
their chosen state and custom status.