Room Manager
vix::realtime::RoomManager coordinates rooms and logical sessions inside one Realtime process.
It is responsible for operations such as:
register room types
open and close rooms
create sessions
join and leave rooms
route commands
manage presence
clean idle rooms
shutdown the runtimeServer provides a higher-level facade over RoomManager, but the manager can also be used directly.
Create a manager
The simplest constructor needs a local node identifier:
#include <vix/realtime.hpp>
vix::realtime::RoomManager manager{
vix::realtime::NodeId{"node-1"}};The default manager uses:
MemoryEventStoreMemorySnapshotStoreLocalPresenceStorewhen presence is enabledRoomDirectory
These dependencies are process-local except for persistence implementations explicitly supplied by the application.
Register a room type
Before opening a room, register its factory:
manager.register_factory(factory);The factory defines how the state and handler for that room type are created.
For example, a factory whose type is:
counterallows the manager to open rooms of that type.
Registering the same type again returns false unless replacement is explicitly allowed.
Open a room
Open a registered room type with:
auto room = manager.open_room(
vix::realtime::RoomId{"room-1"},
"counter");The manager creates the room, registers local ownership, and opens it.
If the same room is already open with the same type, the existing room is returned.
auto sameRoom = manager.open_room(
vix::realtime::RoomId{"room-1"},
"counter");room and sameRoom refer to the same managed room.
Opening rooms is limited by:
config.maxActiveRoomsFind a room
Use find_room() when the room may not exist:
auto room = manager.find_room(
vix::realtime::RoomId{"room-1"});
if (room)
{
// Room exists.
}Use require_room() when absence should be an error:
auto room = manager.require_room(
vix::realtime::RoomId{"room-1"});The number of managed rooms is available with:
auto count = manager.room_count();Create a session
Create a logical session with:
auto session = manager.create_session(
vix::realtime::SessionId{"session-1"},
"user-1");A newly created session has no active transport connection.
The number of logical sessions is limited by:
config.maxSessionsFind a session
Use:
auto session = manager.find_session(
vix::realtime::SessionId{"session-1"});or require an existing session with:
auto session = manager.require_session(
vix::realtime::SessionId{"session-1"});The current number of sessions is available with:
auto count = manager.session_count();Join a room
Use join_room() to add a logical session to a room:
auto result = manager.join_room(
session->id(),
room->id());The manager keeps membership consistent between the two objects:
Session
|
| joined
v
RoomManager
|
v
RoomIf presence is enabled, a presence record is also created or updated.
If the room rejects the join, the manager rolls back the session membership and presence update.
Membership limits
A session cannot join more than:
config.maxRoomsPerSessionrooms.
Each room is also limited by:
config.maxSessionsPerRoomThe manager and room enforce these limits before accepting additional memberships.
Leave a room
Remove a session from a room with:
auto result = manager.leave_room(
session->id(),
room->id());The room lifecycle handler runs before the membership is removed.
If the leave is rejected, the session remains in the room.
When the leave succeeds, the manager removes the session membership and updates presence.
Execute a command
The manager can route a command to its target room:
vix::realtime::RoomCommand command{
room->id(),
session->id(),
"counter.increment"};
auto result = manager.execute(command);Before routing the command, the manager verifies that:
- the session exists
- the session is not closed
- the room exists
- the session belongs to the room
- the room also contains the session membership
The room then performs the actual command execution.
RoomCommand
|
v
RoomManager
|
v
Room
|
v
RoomHandlerQueue a command
A command can also be queued:
auto status = manager.enqueue(
std::move(command));Process the next queued command with:
auto result = manager.process_next(
room->id());If the queue is empty, no result is returned.
Attach a connection
A transport connection can be attached to an existing logical session:
auto previous = manager.attach_connection(
session->id(),
connection);If another connection was already attached, it is returned.
RoomManager::attach_connection() does not close that previous connection automatically.
When presence is enabled, the manager updates the session's room presence to reflect the new connection.
Detach a connection
Detach a specific connection with:
auto connection = manager.detach_connection(
session->id(),
connectionId);The connection is detached only if connectionId matches the currently attached connection.
The logical session remains registered.
Its room memberships are preserved, and presence is marked detached when presence is enabled.
Close a session
Permanently remove a session with:
manager.close_session(
session->id());The manager first removes the session from its joined rooms.
If a room rejects the leave operation, the session is not finally removed.
After successful cleanup, the session is closed and removed from the manager.
Presence
When presence is enabled, the manager coordinates presence with session activity.
Find one presence record with:
auto presence = manager.find_presence(
room->id(),
session->id());List presence for a room with:
auto records =
manager.room_presence(room->id());Presence is updated during operations such as joining, attaching, detaching, leaving, and command activity.
Presence failures do not replace the authoritative room event model.
See Presence for the complete presence lifecycle.
Close a room
Close a room with:
auto result = manager.close_room(
room->id());When closing succeeds, the manager:
- removes session memberships
- clears room presence
- releases local ownership
- removes the room from the manager by default
A rejected room close leaves the room managed.
Idle room cleanup
The manager can remove empty rooms that have remained idle for the configured timeout:
auto removed = manager.cleanup();Only rooms that are:
open
empty
idle long enoughare eligible.
The timeout is configured with:
config.roomIdleTimeoutIf the timeout is zero, cleanup is disabled.
RoomManager does not start a background cleanup task. The application decides when to call cleanup().
Shutdown
Close all managed sessions and rooms with:
manager.shutdown();Shutdown processes sessions first, then rooms.
Persisted event history is not deleted simply because the manager shuts down.
Calling shutdown() again after the runtime has already been cleared is safe.
Runtime dependencies
The configured dependencies are available through:
manager.event_store();
manager.snapshot_store();
manager.presence_store();
manager.room_directory();The local node identifier and configuration are available through:
manager.node_id();
manager.config();Most applications do not need to access these dependencies during normal command processing.
Room ownership
When opening a room, the manager acquires ownership through its RoomDirectory.
RoomManager
|
v
RoomDirectory
|
v
RoomOwnerIf room creation or opening fails, the manager releases or clears the ownership claim and does not keep the failed room registered.
See Room Ownership for the ownership model.
Main workflow
A simple direct RoomManager workflow is:
vix::realtime::RoomManager manager{
vix::realtime::NodeId{"node-1"}};
manager.register_factory(factory);
auto room = manager.open_room(
vix::realtime::RoomId{"room-1"},
"counter");
auto session = manager.create_session(
vix::realtime::SessionId{"session-1"},
"user-1");
manager.join_room(
session->id(),
room->id());
vix::realtime::RoomCommand command{
room->id(),
session->id(),
"counter.increment"};
auto result = manager.execute(command);
manager.shutdown();The manager's role is coordination:
RoomFactory
|
v
RoomManager
/ | \
v v v
Rooms Sessions Presence
|
v
EventStoreApplication state remains owned by rooms and their registered state and handler implementations.
Continue with Sessions for the logical client lifecycle.