29 KiB
data-model Specification
Purpose
The analytics read model stored in MongoDB: the collections, fields, indexes, retention and versioning contract shared by the OpenVidu server (writer) and OpenVidu Dashboard (reader), and the write rules that keep the model consistent when events are delayed, replayed or duplicated.
Requirements
Requirement: Schema version contract
Edition: CE and PRO. The writer SHALL record the schema version it implements in schema_meta (_id: "schema", integer version, writerVersion, updatedAt) at startup. The dashboard SHALL compare that
version with the one it supports and refuse to serve data when the writer is older than its minimum.
Scenario: Writer writes its version
- GIVEN a server with analytics enabled starting against an empty database
- WHEN it finishes initialization
- THEN
schema_metacontains{ _id: "schema", version: <writer schema version> }and the collections and indexes of this specification exist
Scenario: Dashboard rejects an older writer
- GIVEN
schema_meta.versionlower than the dashboard's minimum supported version - WHEN the dashboard starts
- THEN it exits with a message naming both versions and the server version to install
Scenario: Dashboard tolerates a newer writer
- GIVEN
schema_meta.versionhigher than the dashboard's version - WHEN the dashboard starts
- THEN it serves data and
GET /api/v1/inforeports the mismatch as a warning
Requirement: Writer metadata documents
Edition: CE and PRO. Besides schema, schema_meta SHALL hold retention, capabilities and config, which the
writer replaces at every initialization, migration (server-legacy-migration) and reconciler
(server-reconciler); _id: "dashboard" is reserved for non-secret facts written by the dashboard.
Scenario: Retention document
- GIVEN a writer initialized with the default retention
- WHEN
schema_meta_id: "retention"is read - THEN it has
eventsMs,statsMs,tracksMsandrollups5MinMs604 800 000,entitiesMs7 776 000 000,rollupsHourlyMs34 560 000 000,rollupsDailyMs: null(daily rollups kept forever) andupdatedAt
Scenario: Daily rollup retention recorded
- GIVEN a writer initialized with
retention.rollups_daily: 1825d - WHEN
schema_meta_id: "retention"is read - THEN
rollupsDailyMsis 157 680 000 000
Scenario: Capabilities and config documents
- WHEN
schema_meta_id: "capabilities"and_id: "config"are read - THEN
capabilitieshastimeseries,transactions,serverVersionanddetectedAt, andconfighas the writer'sstatsDetail(participant|track) andrecordedAt
Requirement: Entity documents keyed by LiveKit identifiers
Edition: CE and PRO. Each room session, participant session, published track, subscription, egress,
ingress and ingress session SHALL be represented by exactly one document whose _id is its LiveKit
identifier (RM_…, PA_…, TR_…, <trackSid>:<subscriberSid>, EG_…, IN_…, ingress resource_id),
created by the first event that mentions it and updated in place by later events.
Scenario: Events out of order
- GIVEN a
PARTICIPANT_ACTIVEevent processed before itsPARTICIPANT_JOINED - WHEN both have been processed in any order
- THEN there is one
participantsdocument withstatus: "active",joinedAtfrom JOINED andactiveAtfrom ACTIVE
Scenario: Replayed event
- GIVEN a document already updated by an event
- WHEN the same event (same LiveKit event id) is processed again
- THEN the document is unchanged and no counter has moved
Requirement: Writer bookkeeping
Edition: CE and PRO. The set-based counters of rooms, participants, tracks and ingresses documents SHALL be
derived from id sets kept under the writer-only internal field, so that a replayed or reordered event never
counts twice; internal is not part of the read contract: the dashboard never reads it and the API never returns it.
Scenario: Session counted once
- GIVEN a
PARTICIPANT_JOINEDof a STANDARD session already applied to its room - WHEN the same event is applied again in a later batch
- THEN the room's
participants.sessionsis unchanged and equals the size of the STANDARD session id set underinternal
Requirement: Room document
Edition: CE and PRO. A rooms document SHALL describe one room session: identity and lifecycle, node,
configuration, participant/track/egress/ingress counters, traffic, quality, feature flags and retention
fields, with the field list of the shared contract (dashboard-ce/typings/src/data-model).
participants.sessions, unique, active, peakActive and aborted SHALL count STANDARD sessions only;
participants.byKind SHALL count the sessions of every kind.
Scenario: Fields of a room document
- WHEN a room document is read
- THEN it has
name,nameLower,status(active|closed),createdAt,endedAt,durationMs,endReason,closedBy,nodeId,config(max participants, empty and departure timeouts, metadata when allowed),participants { sessions, unique, active, peakActive, aborted, byKind },tracks,egress(by type),ingress,bytes { up, down },quality { scoreSum, scoreCount, minScore, poor, lost },features { egress, ingress, agent, sip },lastEventAt,lastStatsAt,schemaVersion,expiresAt
Scenario: Room lifecycle
- GIVEN
ROOM_CREATED, threePARTICIPANT_JOINED/ACTIVE, onePARTICIPANT_LEFT,ROOM_ENDED (API_DELETE) - WHEN all are processed
- THEN the room has
status: "closed",endReason: "API_DELETE",participants.sessions: 3,participants.active: 0,participants.peakActive: 3,durationMs = endedAt - createdAt,closedBy: "event"
Scenario: Dependent participants do not count as room size
- GIVEN a room with two STANDARD participants and one EGRESS participant
- WHEN counters are read
- THEN
participants.byKind.EGRESSis 1 andparticipants.active/peakActivecount only the two STANDARD participants
Scenario: Only standard participants count as participants
- GIVEN an active room with two active STANDARD participants of different identities, one EGRESS, one INGRESS and one AGENT participant, and one aborted SIP session
- WHEN counters are read
- THEN
participants.sessionsis 2,uniqueis 2,activeis 2,peakActiveis 2,abortedis 0 andparticipants.byKindis{ STANDARD: 2, EGRESS: 1, INGRESS: 1, AGENT: 1, SIP: 1 }
Requirement: Participant session document
Edition: CE and PRO. A participants document SHALL represent one participant session (one SID) with its
identity, room, kind, lifecycle status, connection facts, client facts, track and subscription counters,
traffic, quality and retention fields, with the field list of the shared contract.
Scenario: Fields of a participant document
- WHEN a participant document is read
- THEN it has
identity,identityLower,name,roomSid,roomName,kind,kindDetails,status(joining|active|left|aborted),joinedAt,activeAt,leftAt,durationMs,disconnectReason,closedBy,connectTimeMs,connectionType,region,nodeId,resumes,client { sdk, version, os, osVersion, browser, browserVersion, deviceModel, network, address },permission,isPublisher,metadataandattributes(when allowed),tracks { published, bySource, subscribed, subscribeFailures },bytes,quality,lastEventAt,lastStatsAt,schemaVersion,expiresAt
Scenario: Connection aborted
- GIVEN
PARTICIPANT_JOINEDfollowed byPARTICIPANT_CONNECTION_ABORTED - WHEN both are processed
- THEN the document has
status: "aborted",activeAtabsent,leftAtset anddisconnectReasonfrom the event
Scenario: Reconnect creates a new session
- GIVEN a participant that reconnects with the same identity and receives a new SID
- WHEN
PARTICIPANT_LEFT (DUPLICATE_IDENTITY)and the newPARTICIPANT_JOINEDare processed - THEN two documents exist with the same
identityandroomSid, the firstleftand the secondjoiningoractive
Scenario: Resume keeps the session
- GIVEN an active participant that resumes its signal connection
- WHEN
PARTICIPANT_RESUMEDis processed - THEN the same document stays
activeandresumesincreases by one
Requirement: Track and subscription documents
Edition: CE and PRO. A tracks document SHALL describe one published track (references, media facts,
lifecycle, subscriber counters, final publish statistics) and a track_subscriptions document SHALL
describe one (track, subscriber) pair (references, lifecycle, error, final subscribe statistics).
Scenario: Fields of track and subscription documents
- WHEN a track and a subscription document are read
- THEN the track has
roomSid,participantSid,identity,type,source,mimeType,name,status(published|unpublished),publishedAt,unpublishedAt,durationMs,closedBy,muted,width,height,simulcast,codecs[],encryption,subscribers { current, total, failed },publishStats; and the subscription hastrackSid,roomSid,subscriberSid,subscriberIdentity,publisherSid,publisherIdentity,source,status(requested|subscribed|unsubscribed|failed),error,subscribedAt,unsubscribedAt,durationMs,closedBy,subscribeStats
Scenario: Track closed by participant leave
- GIVEN a published track whose
TRACK_UNPUBLISHEDwas never emitted - WHEN the publisher's
PARTICIPANT_LEFTis processed - THEN the track becomes
unpublishedwithunpublishedAt = leftAtand its open subscriptions becomeunsubscribed
Scenario: Subscription failure
- GIVEN
TRACK_SUBSCRIBE_REQUESTEDthenTRACK_SUBSCRIBE_FAILEDwith an error - WHEN both are processed
- THEN the subscription has
status: "failed"anderrorset, and the subscriber'stracks.subscribeFailuresis 1
Requirement: Egress document
Edition: CE and PRO. An egresses document SHALL describe one egress: room reference, type, source,
lifecycle status with history, timestamps, error, a sanitized request and its outputs, with the field
list of the shared contract. roomNameLower SHALL be the lower-cased roomName, written together with it.
Scenario: Fields of an egress document
- WHEN an egress document is read
- THEN it has
roomSid,roomName,roomNameLower,type(room_composite|web|participant|track_composite|track),sourceType,status(starting|active|ending|complete|failed|aborted|limit_reached),closedBy,startedAt,updatedAt,endedAt,durationMs,error,errorCode,request(sanitized),outputs[] { kind, name or url, location, size, durationMs, status, error, startedAt, endedAt },statusHistory[]with at most 50 entries,retryCount,backupStorageUsed,schemaVersion,expiresAt
Scenario: Egress completes
- GIVEN
EGRESS_STARTED, twoEGRESS_UPDATEDandEGRESS_ENDEDwith status COMPLETE and one file result - WHEN all are processed
- THEN the document has
status: "complete", one output of kindfilewith its filename, location, size and duration, and fourstatusHistoryentries
Scenario: Credentials are never stored
- GIVEN an egress request with S3 credentials and a stream URL containing a key
- WHEN the egress is projected
- THEN
requestcontains no credential field and the stream output URL has its key redacted
Scenario: Room name search field
- GIVEN an egress of room
Demo-Room - WHEN its document is read
- THEN it has
roomName: "Demo-Room"androomNameLower: "demo-room"
Scenario: Web egress without room
- GIVEN a web egress, which has no room
- WHEN its document is read
- THEN it has neither
roomNamenorroomNameLower
Requirement: Ingress and ingress session documents
Edition: CE and PRO. An ingresses document SHALL describe one ingress definition and its aggregate
session facts, and an ingress_sessions document SHALL describe one publishing session (resource_id)
with its room, lifecycle and negotiated media parameters.
Scenario: Fields of ingress documents
- WHEN an ingress and an ingress session document are read
- THEN the ingress has
name,nameLower,inputType(rtmp|whip|url), sanitizedurl,roomName,participantIdentity,participantName,reusable,enabled,enableTranscoding,createdAt,deletedAt,status,lastError,sessions,totalDurationMs,lastSessionAt; and the session hasingressId,ingressName,inputType,roomSid,roomName,participantIdentity,status,error,closedBy,startedAt,endedAt,durationMs,video { mimeType, averageBitrate, width, height, framerate },audio { mimeType, averageBitrate, channels, sampleRate }
Scenario: Reusable ingress with two sessions
- GIVEN
INGRESS_CREATED, thenINGRESS_STARTED/INGRESS_ENDEDtwice with differentresource_id - WHEN all are processed
- THEN one
ingressesdocument hassessions: 2andtotalDurationMsequal to the sum of both sessions, and twoingress_sessionsdocuments exist
Scenario: Stream key is never stored
- GIVEN an RTMP ingress with a stream key
- WHEN it is projected
- THEN no document contains the stream key
Requirement: Raw events
Edition: CE and PRO. The events collection SHALL store one document per stored event, keyed by the LiveKit
event id, with the type, timestamp, lifted entity references, node, a synthetic flag and a payload without
secrets. The set of stored types SHALL be configurable with a default that excludes chatty and sensitive
types.
Scenario: Fields of a raw event
- WHEN a raw event is read
- THEN it has
_id(LiveKit event id),type,ts,roomSid,roomName,participantSid,identity,trackSid,egressId,ingressId,ingressSessionId(those that apply),nodeId,syntheticandpayload
Scenario: Default stored types
- GIVEN default configuration
- WHEN
API_CALL,TRACK_PUBLISHED_UPDATE,TRACK_MAX_SUBSCRIBED_VIDEO_QUALITY,TRACK_SUBSCRIBE_REQUESTEDand two identical consecutiveINGRESS_UPDATEDevents are received - THEN no
API_CALL,TRACK_PUBLISHED_UPDATE,TRACK_MAX_SUBSCRIBED_VIDEO_QUALITYorTRACK_SUBSCRIBE_REQUESTEDdocument is stored and only the firstINGRESS_UPDATEDis stored
Scenario: Room timeline
- GIVEN events of a room within the events retention window
- WHEN
eventsis queried byroomSidandts - THEN every stored event of the room is returned in time order with its lifted references, and none of them is an
API_CALL
Scenario: Closure by the reconciler
- GIVEN an active participant on a dead node
- WHEN the reconciler closes it
- THEN the document has
status: "left"(or"aborted"when it never became active),closedBy: "reconciler",disconnectReason: "RECONCILED"andleftAtequal to the latest oflastStatsAtandlastEventAt
Scenario: Synthetic close event
- GIVEN the reconciler closes a stale participant
- WHEN it records the closure
- THEN an
eventsdocument withtype: "PARTICIPANT_LEFT",synthetic: trueand an_idprefixedAE_SYN_exists
Requirement: Track statistics time series
Edition: CE and PRO. track_stats SHALL hold one document per 30-second flush per participant and
direction (participant mode) or per track and direction (track mode), with normalized units, and
signal/data pseudo-tracks SHALL only add to the participant byte totals, without track_stats documents.
Scenario: Fields of a stats document
- WHEN a stats document is read
- THEN it has
ts,meta { roomSid, participantSid, trackSid (track mode only), kind (up|down), nodeId },score,minScore,medianScore,bytes,packets,packetsLost,rttMs,jitterMs,nacks,plis,firs,frames,layers[] { layer, bytes, packets, frames },mimeType(track mode only)
Scenario: Participant mode merges tracks
- GIVEN
participantmode and one flush with camera and microphone upstream stats of the same participant - WHEN the flush is stored
- THEN one upstream document exists for the participant with
bytesequal to the sum andscoreequal to the mean of the two tracks
Scenario: Fallback without time-series support
- GIVEN a MongoDB-compatible server that rejects time-series collections
- WHEN the writer initializes
- THEN
track_statsis created as a plain collection with the same document shape, the same secondary indexes and a TTL index onts
Requirement: Rollups
Edition: CE and PRO. analytics_5min, analytics_hourly and analytics_daily SHALL hold one document per
scope (global and node:<nodeId>) and bucket with pre-aggregated counters, so that long ranges never read
entity or stats documents. Map keys SHALL be enum names or a fixed vocabulary, never user input. Every
participant counter SHALL count STANDARD sessions only, except participants.byKind and the 5-minute
participants.connected (participants with stats), which count every kind.
Scenario: Fields of the rollup documents
- WHEN hourly or daily rollup documents are read
- THEN they have counters for rooms (created, ended, by end reason,
durationMsSum,participantsSum), participants (joined, active, aborted, left, by kind, SDK, OS, browser, connection type, disconnect reason, connect time, minutes), tracks, egress (started, by type, by end status, duration), ingress sessions (started, ended, started by input type, duration), bytes, quality (score sum/count, poor, lost), API calls and API errors (total and by method), and daily documents alsouniqueIdentities(set by the server's reconciler once the UTC day has closed); 5-minute documents have bytes, quality,participants.connected(distinct participants with stats), thePARTICIPANT_ACTIVEcount and the lifecycle counters (rooms created/ended, participants joined/left/aborted, egress started/ended)
Scenario: Five-minute bandwidth
- GIVEN stats flushed between 10:00 and 10:05 UTC
- WHEN
analytics_5minis read forglobal:…T10:00:00Z - THEN
bytes.upandbytes.downequal the sum of the flushed upstream and downstream bytes andquality.scoreCountequals the number of samples
Scenario: Hourly counters
- GIVEN five rooms created and two ended between 10:00 and 11:00 UTC on one node
- WHEN the events are processed
- THEN
analytics_hourlyhasglobal:2026-…T10:00:00Zandnode:<id>:2026-…T10:00:00Zwithrooms.created: 5androoms.ended: 2
Scenario: Replayed batch does not double count
- GIVEN a batch whose raw events were already inserted
- WHEN the batch is processed again
- THEN rollup counters are unchanged
Scenario: Services in rollups
- GIVEN between 10:00 and 11:00 UTC three STANDARD, one EGRESS and one AGENT participant joined, and the AGENT left after 10 minutes
- WHEN the hourly rollup is read
- THEN
participants.joinedis 3,participants.leftis 0,participants.minutescounts only the STANDARD sessions andparticipants.byKindis{ STANDARD: 3, EGRESS: 1, AGENT: 1 }
Scenario: Ingress sessions by input type
- GIVEN two RTMP and one WHIP ingress sessions started between 10:00 and 11:00 UTC
- WHEN the hourly rollup is read
- THEN it has
ingress.sessionsStarted: 3andingress.byInputType: { rtmp: 2, whip: 1 }
Requirement: Nodes
Edition: CE and PRO. The nodes collection SHALL hold one document per server node with firstSeenAt,
lastSeenAt, serverVersion, region and batchIntervalMs (int32 milliseconds, at least 1 000: the node's
configured batch interval), updated by every writer batch, and SHALL expire documents 30 days after their last
heartbeat so decommissioned nodes disappear. A document without batchIntervalMs SHALL be read as a 10 s interval.
Scenario: Node heartbeat
- GIVEN a node writing batches every 10 s
- WHEN
nodesis read - THEN its document has
lastSeenAtwithin the last batch interval andbatchIntervalMs: 10000
Scenario: Node document without the interval
- GIVEN a
nodesdocument withoutbatchIntervalMs - WHEN the dashboard derives that node's freshness windows
- THEN it uses a 10 000 ms interval
Scenario: Interval below the minimum
- GIVEN the test configuration
- WHEN a
nodesdocument withbatchIntervalMs: 500is written - THEN the write is rejected by the validator
Requirement: Retention
Edition: CE and PRO. Retention SHALL be configurable per class with defaults events 7 d, stats 7 d,
tracks (tracks and subscriptions) 7 d, entities (rooms, participants, egress, ingress) 90 d, 5-minute rollups 7 d,
hourly rollups 400 d, daily rollups unlimited unless configured. A closed entity document SHALL carry expiresAt = its
end time plus its class retention, computed when written, and an open one expiresAt: null; events, track_stats
and the rollups expire by TTL indexes.
Scenario: TTL indexes
- GIVEN a writer that finished initialization with the default retention
- WHEN the TTL indexes are listed
- THEN
eventsexpires bytsafterretention.events,track_statsbytsafterretention.stats,analytics_5minbybucketafterretention.rollups_5min,analytics_hourlybybucketafterretention.rollups_hourly, every entity collection byexpiresAtwithexpireAfterSeconds: 0,nodesbylastSeenAtafter 30 days, andanalytics_dailyhas no TTL index
Scenario: Daily rollups with a retention
- GIVEN a writer that finished initialization with
retention.rollups_daily: 1825d - WHEN the TTL indexes of
analytics_dailyare listed - THEN it expires by
bucketafter 1 825 days
Scenario: Expiry of closed entities
- WHEN closed entity documents are read
- THEN
expiresAtisendedAt+retention.entitiesfor rooms,leftAt+retention.entitiesfor participants,endedAt(elseupdatedAt) +retention.entitiesfor egresses in a terminal status,endedAt(elsestartedAt) +retention.entitiesfor ended ingress sessions,unpublishedAt+retention.tracksfor tracks,unsubscribedAt+retention.tracksfor subscriptions and the failure time +retention.tracksfor failed subscriptions
Scenario: Ingress definition
- GIVEN a reusable ingress
- WHEN its document is read before and after its
INGRESS_DELETED - THEN
expiresAtisnullbefore, whatever its sessions, anddeletedAt+retention.entitiesafter
Scenario: Entities retention change
- GIVEN a room closed while
retention.entitieswas90d - WHEN the writer restarts with
retention.entities: 30d - THEN that room keeps its
expiresAtand rooms closed afterwards getendedAt+ 30 days
Scenario: Active entity never expires
- GIVEN a room active for longer than the entities retention
- WHEN the TTL monitor runs
- THEN the room document exists
Scenario: Retention change applies to existing data
- GIVEN a deployment that changes
retention.eventsfrom 7 d to 30 d - WHEN the writer restarts
- THEN the TTL index of
eventshas the newexpireAfterSecondsandschema_meta(_id: "retention") reflects the configured values
Requirement: Secrets and personal data
Edition: CE and PRO. No document SHALL contain turn_password, storage credentials, stream keys, signing
keys, tokens or SIP credentials. Client IP addresses SHALL be stored only when anonymize_ip is false, and
participant metadata, attributes, room metadata and ingress participant metadata SHALL be stored only when
store_metadata is enabled.
Scenario: Anonymized IP
- GIVEN the default configuration
- WHEN a
PARTICIPANT_JOINEDwithclient_info.addressis projected - THEN
client.addressis absent from the participant document and from the raw event payload
Scenario: IP addresses stored on request
- GIVEN
anonymize_ip: false - WHEN a
PARTICIPANT_JOINEDwithclient_info.addressis projected - THEN the participant document has
client.address
Scenario: Metadata disabled by default
- GIVEN default configuration
- WHEN a room with metadata and a participant with attributes are projected
- THEN neither
config.metadatanormetadata/attributesare stored
Requirement: Index-backed queries
Edition: CE and PRO. The writer SHALL create the indexes of the shared contract
(dashboard-ce/typings/contract/indexes.ts) at initialization, and every list, detail and time-series query of the
dashboard API SHALL use an index (no collection scan) on collections with more than a configurable threshold of
documents.
Scenario: Explain plans in tests
- GIVEN a database generated by the data generator at scenario M
- WHEN each API query is explained
- THEN no winning plan contains a
COLLSCANstage andtotalDocsExaminedis bounded by the page size plus the filtered range
Requirement: Units and time
Edition: CE and PRO. All timestamps SHALL be stored as UTC Date, durations as integer milliseconds and
sizes as integer bytes; the writer SHALL convert the protocol's seconds, milliseconds, nanoseconds and
microseconds accordingly. Bucketing by calendar unit SHALL be done at read time with the caller's timezone.
Scenario: Egress nanoseconds normalized
- GIVEN an
EgressInfowithstarted_atandended_atin nanoseconds - WHEN projected
- THEN
startedAtandendedAtareDatevalues anddurationMsis their difference in milliseconds
Requirement: Document validators
Edition: CE and PRO. Each collection SHALL have a JSON Schema validator derived from the shared contract,
applied with validationAction: "warn" in production and "error" in tests, so a writer defect is
visible in logs without losing data.
Scenario: Invalid document in tests
- GIVEN the test configuration
- WHEN a room document with
createdAtas a string is inserted - THEN the insert is rejected by the validator
Requirement: Egress room-name search index
Edition: CE and PRO. egresses SHALL have the index roomNameLower_startedAt { roomNameLower: 1, startedAt: -1 },
partial on roomNameLower existing, which backs the case-insensitive prefix search on the egress room name with the
range on startedAt. An egress document without roomNameLower is not matched by that search.
Scenario: Index of an initialized database
- GIVEN a writer that finished initialization
- WHEN the indexes of
egressesare listed - THEN
roomNameLower_startedAtexists with the key{ roomNameLower: 1, startedAt: -1 }and the partial filter{ roomNameLower: { $exists: true } }
Scenario: Document without the search field
- GIVEN an egress document of room
demo-roomwithoutroomNameLower - WHEN the egress list is searched by the room name
demo - THEN that egress is not returned, and egresses of the same room that carry
roomNameLowerare
Requirement: Ingress last-session index
Edition: CE and PRO. ingresses SHALL have the index lastSessionAt_id { lastSessionAt: -1, _id: -1 }, partial on
lastSessionAt existing, which backs the selection of the ingresses whose last session started in a time range.
Scenario: Index of an initialized database
- GIVEN a writer that finished initialization
- WHEN the indexes of
ingressesare listed - THEN
lastSessionAt_idexists with the key{ lastSessionAt: -1, _id: -1 }and the partial filter{ lastSessionAt: { $exists: true } }
Requirement: Generated data follows the writer's shape
Edition: CE and PRO. The data generator SHALL write documents in the writer's shape: event payloads as the writer's
protojson (snake_case names nested under room, participant, track, egress and ingress, 64-bit integers as
64-bit numbers, as in the contract event fixtures), ingress nameLower and egress roomNameLower as the lower-cased
name and roomName, and node heartbeats with batchIntervalMs 10 000.
Scenario: Generated event payload
- GIVEN a database generated by the data generator
- WHEN a generated
PARTICIPANT_JOINEDevent is read - THEN its payload has
room.sid,participant.sid,participant.identityandclient_info.sdk, has no camelCase key such asclientInfo, and satisfies the payload interfaces of the typings
Scenario: Lower-cased search fields
- GIVEN a generated ingress named
Studio-Aand a generated egress of roomDemo-Room - WHEN their documents are read
- THEN the ingress has
nameLower: "studio-a"and the egress hasroomNameLower: "demo-room"
Scenario: Generated node heartbeats
- GIVEN a database generated by the data generator, kept live by its keep-alive
- WHEN
nodesis read - THEN every document has
batchIntervalMs: 10000