Event Store
vix::realtime::EventStore is the persistence interface for authoritative room events.
Each room has its own ordered event stream.
Room A
1 2 3 4
Room B
1 2The room runtime persists accepted events before applying them to RoomState.
RoomEvent
|
v
EventStore
|
v
RoomState::apply()Default event store
The default Realtime runtime uses:
vix::realtime::MemoryEventStoreYou can access the configured store through the room manager:
auto store =
server.manager()->event_store();Most applications do not need to append events directly. Room normally handles persistence after a command is accepted.
EventStore interface
An event store provides these operations:
append()
append_batch()
load_after()
latest_event_id()
count()
clear_room()The same interface is used by the in-memory and PostgreSQL implementations.
Append an event
append() persists one event:
vix::realtime::MemoryEventStore store;
vix::realtime::RoomEvent event{
vix::realtime::RoomId{"room-1"},
"counter.incremented"};
event.set_room_version(
vix::realtime::RoomVersion{1});
auto stored =
store.append(std::move(event));The store assigns the persistent EventId.
The first event in a room receives:
EventId 1The next receives:
EventId 2and so on.
In normal room processing, the runtime prepares the room version before sending the event to the store.
Event IDs are assigned by the store
An event passed to append() must not already contain a persistent event ID.
before append
EventId = 0
after append
EventId = 1Applications should not assign persistent event IDs themselves.
Room versions must be contiguous
The event store also verifies room-version ordering.
For example, this sequence is valid:
RoomVersion 1
RoomVersion 2
RoomVersion 3This sequence is invalid:
RoomVersion 1
RoomVersion 3The store rejects the second sequence because version 2 is missing.
RoomVersion and EventId remain separate values:
RoomVersion
logical state version
EventId
persisted event positionAppend multiple events
Use append_batch() to persist several events atomically:
std::vector<vix::realtime::RoomEvent> events;
// Add events for the same room.
auto stored =
store.append_batch(
std::move(events));Every event in the batch must:
- belong to the same room
- have a contiguous room version
- have no persistent event ID yet
Either the complete batch is persisted or none of it is.
event 1
event 2
event 3
|
v
append_batch()
|
+---- all stored
|
or
|
+---- none storedRooms use this operation when one accepted command produces multiple events.
Load events
Use load_after() to read events from a room stream:
auto events =
store.load_after(
roomId,
vix::realtime::EventId{},
100);An empty EventId starts from the beginning of the stream.
The returned events are ordered by ascending event ID.
1
2
3
4Load after a cursor
Pass an existing event ID to continue after it:
auto events =
store.load_after(
roomId,
vix::realtime::EventId{3},
100);For this stream:
1 2 3 4 5
^
cursorthe result contains:
4 5The cursor itself is excluded.
This behavior is used by replay and session recovery.
Limit results
The final argument limits how many events are returned:
auto events =
store.load_after(
roomId,
vix::realtime::EventId{},
2);If the room contains:
1 2 3 4the result contains at most:
1 2A limit of zero returns no events.
Latest event ID
Get the latest persisted position with:
auto eventId =
store.latest_event_id(roomId);For:
1 2 3 4the latest event ID is:
4An empty room stream returns an empty EventId.
Count events
Get the number of persisted events with:
auto count =
store.count(roomId);An unknown or empty room stream returns:
0Independent room streams
Event ordering is maintained independently for each room.
For example:
room-1
EventId 1
EventId 2
EventId 3
room-2
EventId 1
EventId 2Appending an event to one room does not advance the event ID of another room.
Clear a room stream
Delete all persisted events for one room with:
bool removed =
store.clear_room(roomId);The operation returns true when a stream existed and was removed.
It returns false when the room had no stored stream.
clear_room() is intended for explicit deletion, administrative cleanup, and tests.
Normal room closing or server shutdown does not delete event history.
MemoryEventStore
MemoryEventStore keeps event streams in process memory:
vix::realtime::MemoryEventStore store;It is suitable for:
- tests
- examples
- development
- single-process applications that do not require durable event history
Its contents disappear when the process ends.
The implementation is thread-safe and keeps each room stream independently ordered.
It also provides:
store.clear();to remove all in-memory room streams.
The number of stored room streams is available with:
auto count =
store.room_count();Durable persistence
Realtime also provides:
vix::realtime::PostgresEventStorefor durable PostgreSQL-backed event storage.
It implements the same EventStore interface:
EventStore
|
+---- MemoryEventStore
|
+---- PostgresEventStoreApplication room logic does not need to change when the event store implementation changes.
PostgreSQL configuration and database behavior are covered in PostgreSQL.
Event store failures
Persistence failures are reported as Realtime errors.
A room does not apply an accepted event to its authoritative state if the event batch could not first be persisted.
persist fails
|
v
do not apply event
to RoomStateThis ordering prevents the in-memory authoritative state from advancing ahead of its persisted event history.
Event store and replay
Persisted events are used to reconstruct room state.
EventStore
|
v
load ordered events
|
v
RoomState::apply()
|
v
restored stateA snapshot can provide a later starting point, after which only newer events need to be loaded.
snapshot
|
v
load events after snapshot
|
v
current stateSee Snapshots and Replay and Recovery for the recovery workflow.
Main rules
The important event-store guarantees are:
each room has its own ordered stream
EventId is assigned by the store
room versions must remain contiguous
batch appends are atomic
load_after() uses an exclusive cursor
events are persisted before state application
normal shutdown preserves event historyThe event store provides the durable history from which authoritative room state can be reconstructed.
Continue with Snapshots for storing recovery checkpoints.