Presence
Presence describes whether a logical session is currently participating in a room.
It is separate from authoritative RoomState.
RoomState
application state
Presence
session participationExamples of presence information include whether a session is connected, temporarily detached, or has left the room.
Presence states
A presence record has three states:
Present
Detached
LeftThe normal lifecycle is:
Present
|
disconnect
v
Detached
|
reconnect
v
PresentWhen the session permanently leaves the room:
Present or Detached
|
v
LeftRead room presence
Presence is normally managed automatically by RoomManager.
List the current presence records for a room with:
auto records =
server.manager()->room_presence(
roomId);Each record represents one logical session in that room.
Find one presence
Find the presence of one session with:
auto presence =
server.manager()->find_presence(
roomId,
sessionId);The result is optional:
if (presence)
{
auto status = presence->status();
}Present
Present means the logical session is currently present in the room.
Check it with:
if (presence->status() ==
vix::realtime::PresenceStatus::Present)
{
// Present in the room.
}A present record may also contain an active connection identifier.
Check whether it currently represents an attached connection with:
if (presence->connected())
{
// An active connection ID is available.
}Present and connected() are not identical. A presence can be logically present without exposing a connection identifier.
Detached
A detached session remains logically present in the room even though its transport connection has been lost.
if (presence->detached())
{
// Temporarily disconnected.
}Its active connection identifier is cleared.
The room membership remains intact, which allows session resumption to restore the transport connection later.
room membership
|
v
Present
|
connection lost
|
v
DetachedSee Session Resume for reconnection behavior.
Left
Left means the session permanently left the room.
if (presence->left())
{
// No longer logically present.
}A left presence is no longer considered logically present.
presence->logically_present();returns false for Left.
Logical presence
Use:
bool present =
presence->logically_present();This returns true for:
Present
Detachedand false for:
LeftA temporary network disconnection therefore does not immediately remove the logical participant from the room.
Join behavior
When a session joins a room through the manager:
server.join_room(
sessionId,
roomId);Realtime creates a presence record when presence tracking is enabled.
If the session has an active connection, the presence starts as:
PresentIf the session has no active connection, it starts as:
DetachedPresence creation is coordinated with room membership. If the join operation fails, the new presence record is removed.
Connection attachment
When a connection is attached:
server.manager()->attach_connection(
sessionId,
connection);Realtime marks the session as present in each room it has joined.
Detached
|
connection attached
v
PresentThe presence record receives the active connection identifier and the local node identifier.
Connection detachment
When the current connection is detached:
server.manager()->detach_connection(
sessionId,
connectionId);Realtime marks the session's joined-room presence as detached.
Present
|
connection detached
v
DetachedThe room membership remains unchanged.
Leave behavior
When a session leaves:
server.leave_room(
sessionId,
roomId);its presence is marked:
LeftA left record can remain stored until it is pruned or explicitly removed.
Normal room presence listings exclude records that have already reached Left.
Presence activity
Each presence record tracks:
presence->joined_at();
presence->last_seen_at();For detached records, it also tracks:
presence->detached_at();For left records:
presence->left_at();These timestamps allow the runtime to distinguish recent presence from stale records.
Command activity
Executing or enqueueing a command through RoomManager updates the presence activity timestamp for that room membership.
For example:
server.execute(command);updates the corresponding presence before routing the command to the room.
Presence activity is best-effort runtime information. A presence update failure does not replace the room's authoritative event processing.
Presence timeout
Stale presence cleanup uses:
config.presenceTimeoutThe default is:
90 secondsA presence becomes stale when its inactivity reaches the configured timeout.
Both present and detached records can become stale.
A Left record is always considered stale.
Remove stale presence
The server can remove stale presence records with:
auto removed =
server.prune_stale_presence();The operation uses the configured presenceTimeout.
For example:
last activity
|
| presenceTimeout
v
presence becomes stale
|
v
prune_stale_presence()
|
v
record removedCleanup is explicit. Realtime does not start a background presence-cleanup thread.
Presence store
Presence records are stored through the PresenceStore interface.
The default runtime uses:
vix::realtime::LocalPresenceStorewhen presence tracking is enabled.
The configured store is available with:
auto store =
server.manager()->presence_store();It may be null when presence is disabled.
Disable presence
Presence tracking is enabled by default:
config.enablePresence = true;Disable it with:
config.enablePresence = false;Rooms, sessions, commands, and authoritative event processing can still operate without a presence store.
Presence is an additional participation model, not the source of authoritative room state.
PresenceStore operations
A presence store supports operations such as:
upsert
find
touch
mark present
mark detached
mark left
list room
list session
erase
prune staleMost applications should use Server and RoomManager for normal membership and connection workflows rather than updating the store manually.
This keeps session membership and presence transitions coordinated.
Presence metadata
Presence can contain application-defined metadata:
auto metadata =
presence->metadata();Metadata is non-authoritative.
It can be used for information associated with a participant, but application state that must survive replay should live in RoomState and persisted events.
Node information
A presence record may contain the node currently reporting it:
auto nodeId =
presence->node_id();The local RoomManager records its own NodeId when it creates or restores managed presence.
This field supports the presence model used by multi-node coordination, but the default LocalPresenceStore remains local to one process.
Distributed presence is covered separately in Distributed Presence.
Presence and room state
Presence must not be confused with authoritative state.
For example:
authoritative RoomState
score = 10
match = running
document = "hello"belongs in persisted room events and state.
Information such as:
session is connected
session is detached
last activity time
connection IDbelongs in presence.
The separation is:
RoomState
durable application truth
reconstructed through events
Presence
runtime participation
connection-aware
may expireMain lifecycle
The normal presence workflow is:
join room
|
v
Present or Detached
|
+---- connection attaches
| |
| v
| Present
|
+---- connection detaches
| |
| v
| Detached
|
+---- leave room
|
v
LeftPresence tracks the lifecycle of a logical participant without making temporary network state part of the room's authoritative application state.
Continue with Event Store for how authoritative room events are persisted.