-
-
Notifications
You must be signed in to change notification settings - Fork 53
Reconnection
- The network between your client and server is unreliable (mobile, hotel WiFi, VPN drops).
- You want clients to automatically rejoin their namespaces and rooms after a drop.
- You need to know on the server side whether a connecting client is a reconnect attempt.
Reconnection is client-driven. The server doesn't track sessions for offline clients — it simply accepts the next handshake and assigns a fresh Conn.ID. The client carries enough state (previously connected namespaces and joined rooms) to rejoin transparently.
The flow:
- Connection drops (server crash, network failure, sleep/wake).
- Client's
whenResourceOnlineloop pings the HTTP endpoint with aHEADrequest everyreconnectms. - Once the endpoint replies, the client dials again with an
X-Websocket-Reconnect: Nheader whereNis the retry count. - Server's
UpgradesetsConn.ReconnectTries = N. The original clientDialcall returns this newConn. - Client re-runs
connect(namespace)andjoinRoom(room)for each namespace+room recorded before the drop.
const conn = await neffos.dial("ws://localhost:8080/echo", handlers, {
reconnect: 5000, // try every 5 seconds while offline
});Breaking note (neffos.js 0.2.0): the option is
reconnect. Versions ≤ 0.1.34 declaredreconnnect(three n's) inindex.d.ts, which silently disabled the feature for TypeScript users. Update both your import and your call sites if upgrading.
The Go client does not have a built-in reconnect — call Dial again in a loop if you need it server-to-server.
if (conn.wasReconnected()) {
console.log("reconnected after", conn.reconnectTries, "attempts");
}Two places to look:
// 1. From inside Upgrade / OnConnect (or any event):
if c.WasReconnected() {
log.Printf("client %s reconnected after %d tries", c.ID(), c.ReconnectTries)
}
// 2. If you call Server.Upgrade directly and want to distinguish "this was a
// reconnect probe, not a real failure":
if neffos.IsTryingToReconnect(err) {
// The HEAD probe — respond and let the client dial again.
return
}IsTryingToReconnect returns true for the HTTP HEAD probe the client sends while waiting for the endpoint to come back online. The server returns 302 Found automatically; you do not have to handle this case unless you call Upgrade from a custom handler.
The client snapshots connectedNamespaces and joined room names before clearing them on disconnect, then walks the snapshot on reconnect and calls connect() + joinRoom() for each. If a namespace or room no longer exists on the new server (e.g. after a redeploy), the rejoin attempt for that entry logs a warning and the others continue.
If you need different rejoin behavior (e.g. user confirmation before rejoining), connect once and then handle reconnect manually by listening for the OnNamespaceConnected event and detecting wasReconnected().
Two cases where the client does not attempt reconnect:
-
The server force-disconnected the client. Detected via
isCloseError(err). Don't retry — the server explicitly said go away. -
The client called
close()itself. Internal flag stops the reconnect loop.
In both cases Conn.isClosed() is true at the time of onclose.
sequenceDiagram
autonumber
participant C as Client
participant S as Server
C->>S: WebSocket handshake (initial)
S-->>C: 101 Switching Protocols
Note over C,S: connection healthy
Note over C: network drops
C->>S: HEAD /echo (probe, every reconnect ms)
S-->>C: 302 Found (errUpgradeOnRetry)
C->>S: GET /echo + X-Websocket-Reconnect: 3
S-->>C: 101 Switching Protocols
Note over S: Upgrade sets c.ReconnectTries = 3
C->>S: connect("default")
S-->>C: ack
C->>S: joinRoom("lobby")
S-->>C: ack
Note over C,S: state restored
A simple manual test: launch a server, dial from a browser with reconnect: 2000, stop the server, restart it. Watch the browser DevTools — you should see HEAD requests every 2s, then a new WebSocket handshake, then OnNamespaceConnected re-firing for each previously connected namespace.
-
Errors —
IsCloseErrorvsIsDisconnectErrorvsIsTimeoutError - Authentication — token refresh during reconnect
- Architecture — the ack handshake and connection lifecycle
Home | About | Project | Getting Started | Technical Docs | Copyright © 2019-2023 Gerasimos Maropoulos. Documentation terms of use.
Getting started
Concepts
Messaging
Production
Scale out