CollaborationService
Realtime session management with state machine lifecycle
CollaborationService manages realtime collaboration sessions. Each board has at most one active session at a time.
Session State Machine
created → active → idle → archived| State | Description |
|---|---|
created | Session initialized, waiting for first participant |
active | At least one participant is connected |
idle | All participants disconnected, idle timer running |
archived | Idle timeout reached; session data flushed and cleaned up |
Transitions:
created → active: First participant joinsactive → idle: Last participant leavesidle → active: A participant reconnects before timeoutidle → archived: Timeout expires (5 min for ephemeral, 15 min for persistent)
BoardSession
interface BoardSession {
boardId: string;
participants: Map<string, Participant>;
pendingMutations: ElementMutation[];
currentSequence: number;
lastFlush: number;
state: SessionState;
idleSince: number | null;
sessionType: 'ephemeral' | 'persistent';
}
type SessionState = 'created' | 'active' | 'idle' | 'archived';Methods
joinSession
Joins or creates a session. Returns sync information for the client.
async joinSession(
boardId: string,
userId: string,
displayName: string,
lastSequence?: number,
sessionType?: 'ephemeral' | 'persistent',
): Promise<JoinResult>;interface JoinResult {
session: BoardSession;
syncType: 'full' | 'delta';
missedMutations?: ElementMutation[];
}- If
lastSequenceis provided and fewer than 1000 events have occurred since, returnssyncType: 'delta'withmissedMutations. - Otherwise returns
syncType: 'full'(client should fetch complete board state).
leaveSession
Removes a participant. Transitions to idle if no participants remain.
async leaveSession(boardId: string, userId: string): Promise<void>;applyMutations
Applies element mutations, logs events, and increments the sequence counter. Returns the new sequence number.
async applyMutations(
boardId: string,
userId: string,
mutations: ElementMutation[],
): Promise<number>;flushPending
Persists all pending mutations to storage. Groups element upserts by page.
async flushPending(boardId: string): Promise<void>;getSessionState
Returns the current session for a board, or null if no session exists.
async getSessionState(boardId: string): Promise<BoardSession | null>;getSessionStats
Returns aggregate statistics across all active sessions.
getSessionStats(): SessionStats;interface SessionStats {
activeSessions: number;
idleSessions: number;
totalParticipants: number;
}closeSession
Flushes pending mutations and removes the session.
async closeSession(boardId: string): Promise<void>;Idle Timeout Behavior
The service runs a background interval (every 60 seconds) that checks for idle sessions:
| Session Type | Idle Timeout | On Archive |
|---|---|---|
ephemeral | 5 minutes | Flush pending mutations, delete session |
persistent | 15 minutes | Flush pending mutations, create snapshot, delete session |
Persistent sessions create a snapshot of all page elements when archived, stored via EventLogStorage.createSnapshot().
Participant Colors
Participants are assigned colors from a rotating palette when they join:
#FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7, #DDA0DD, #98D8C8, #F7DC6FThe color index is based on the number of existing participants modulo the palette size.