openvidu/openvidu-dashboard/openspec/changes/writer-review-fixes/specs/server-analytics-writer/spec.md

4.3 KiB

MODIFIED Requirements

Requirement: Lifted keys and room resolution

Edition: CE and PRO. Every document SHALL carry lifted references resolved from the event: ROOM_CREATED from room.sid, egress events from egress.room_id and egress.room_name, ingress events from ingress.state.room_id, which the server fills from the active room of ingress.room_name when the ingress reports none, and ingress.room_name, track events from the minimal room {sid, name}; a missing room leaves the reference absent.

Scenario: ROOM_CREATED without room_id

  • GIVEN a ROOM_CREATED event with empty room_id, room.sid = "RM_x" and room.creation_time_ms
  • WHEN it is projected
  • THEN the rooms document has _id: "RM_x" and createdAt from creation_time_ms, and the raw event has roomSid: "RM_x"

Scenario: Egress before any room event

  • GIVEN an EGRESS_STARTED with egress.room_id and egress.room_name and no prior room event
  • WHEN it is projected
  • THEN the egresses document and the raw event carry roomSid and roomName, and the rooms document is upserted with features.egress: true and its egress counter

Scenario: Web egress without room

  • GIVEN a web egress with empty room_id
  • WHEN it is projected
  • THEN roomSid is absent from the egress document and the raw event, and no rooms write model is produced

Scenario: Ingress session key

  • GIVEN an INGRESS_STARTED with ingress.state.resource_id
  • WHEN it is projected
  • THEN the ingress_sessions document has _id equal to resource_id, ingressId and roomSid from state.room_id, and the raw event has ingressSessionId

Scenario: Ingress publishing before its state names the room

  • GIVEN an ingress of room qa-ingress, active as RM_x, whose service sends the publishing state without room_id
  • WHEN the server handles the state update and the writer projects its INGRESS_STARTED
  • THEN the event carries state.room_id: "RM_x", the ingress_sessions document has roomSid: "RM_x" while it publishes, and the room counts the session as active

Scenario: Ingress of a room that is not active

  • GIVEN an ingress whose state has no room_id and whose room name has no active room
  • WHEN the server handles the state update
  • THEN the state keeps no room_id and the session document has no roomSid until an event names the room

Scenario: Subscriber identity resolved

  • GIVEN a participant session PA_1 already projected with identity alice
  • WHEN a TRACK_SUBSCRIBED with participant {sid: "PA_1"} and publisher {sid, identity} is processed
  • THEN the subscription has subscriberIdentity: "alice", publisherSid and publisherIdentity from publisher

Requirement: Rollup counters from events

Edition: CE and PRO. Each projected event SHALL increment the hourly and daily counters of its UTC bucket in both scopes, and its 5-minute lifecycle counters, once: an event stored raw counts only when its raw insert succeeds, so an event already stored by a previous process never counts again; an event not stored raw counts when it is projected; an in-process retry never reapplies a rollup step that succeeded. Map keys SHALL be enum names or a fixed vocabulary, never user input.

Scenario: Batch retried after a transient error

  • GIVEN a batch whose raw inserts succeeded and whose rollup step failed with a network error
  • WHEN the batch is retried
  • THEN raw inserts are skipped as duplicates, the rollup step is applied once and the counters equal the event counts

Scenario: Replayed events from another process

  • GIVEN events already stored by a previous process
  • WHEN they are processed again
  • THEN the rollup counters are unchanged

Scenario: Vocabulary keys

  • GIVEN a PARTICIPANT_JOINED with client_info.sdk: JS, os: "Windows 11" and browser: "Chrome 130"
  • WHEN it is projected
  • THEN the hourly rollup increments participants.bySdk.JS, participants.byOs.windows and participants.byBrowser.chrome, and a value outside the vocabulary increments other

Scenario: Session without a browser

  • GIVEN a PARTICIPANT_JOINED with client_info.sdk: GO and an empty browser
  • WHEN it is projected
  • THEN the hourly rollup increments participants.byBrowser.none, not participants.byBrowser.other