Append an audit-log entry for this room. Public so the http upgrade handler can log connect/disconnect.
Optionaldetail: Record<string, unknown>Tear down a room that never finished loading. Same disposal as
destroy() MINUS the final compaction: this room's doc is empty or
partial because loadFromDisk() threw, so compacting it would replace
the persisted log with that emptiness -- turning a transient disk error
(EMFILE, ENOSPC, an NFS blip) or a corrupt log into permanent data loss.
Compaction is only ever valid for a doc that loaded successfully.
Receive a binary message from a peer and dispatch it.
Force-disconnect the peer that owns the given awareness clientId (admin
"kick"). Closing the socket triggers the normal removeConnection cleanup,
which clears the peer's awareness state for everyone. Returns whether a
matching connection was found plus the peer's token jti (if any) so the
caller can revoke it — otherwise the client's y-websocket simply reconnects
with the same still-valid token.
Send an application-level keepalive to one peer.
y-websocket's client closes a connection after
messageReconnectTimeout (30s, a module-level const, not configurable)
with no inbound MESSAGE, and only websocket.onmessage refreshes that
clock (y-websocket/src/y-websocket.js:186,387-396). WebSocket protocol
pings do not count: they are auto-ponged below the message layer, so the
ws.ping() loop in server.ts cannot feed it.
This server does not echo a peer's own updates back to it
(if (conn === origin) continue; below, and the same for doc updates), so
a room with ONE occupant produces no server-to-client traffic at all after
the initial handshake. y-websocket's own comment says the timeout assumes
"not even your own awareness updates (which are updated every 15 seconds)"
come back, i.e. the reference server echoes them and ours does not.
Until #2791 that gap was masked by an accident: the server's own Awareness ghost state renewed every ~15s and was broadcast to everyone, feeding the watchdog. Clearing the ghost removes the accident, so the keepalive has to be explicit. Measured: with the ghost gone and no keepalive, a lone client closed and reconnected at t=30s and t=63s over a 75s window; with either one present, zero closes.
#3441 periodic expiry re-check; see principal-expiry.ts.
Optionalnow: number
Number of currently connected peers.