// Package roomtime defines user-scoped in-room duration facts. package roomtime const ( // RoomUserJoinedEventType opens an in-room session when the durable outbox fact arrives. RoomUserJoinedEventType = "RoomUserJoined" // RoomUserLeftEventType closes an in-room session on voluntary or stale-swept leave. RoomUserLeftEventType = "RoomUserLeft" // RoomUserKickedEventType closes an in-room session; kick/system evict/close room 只发该事实,不再补 RoomUserLeft。 RoomUserKickedEventType = "RoomUserKicked" // SessionStatusOpen means the user is considered inside the room by the read model. SessionStatusOpen = "open" // SessionStatusEnded is terminal and must never be reopened by replayed events. SessionStatusEnded = "ended" // EventTypeUserRoomDailyStatsUpdated is emitted for each UTC day touched by a closed session. EventTypeUserRoomDailyStatsUpdated = "UserRoomDailyStatsUpdated" // EndReasonLeft closes a session from RoomUserLeft. EndReasonLeft = "left" // EndReasonKicked closes a session from RoomUserKicked(含系统驱逐与关房清场). EndReasonKicked = "kicked" // EndReasonSupersededByJoin closes a lingering open session in another room when a newer join arrives. EndReasonSupersededByJoin = "superseded_by_join" // EndReasonSupersededByRejoin closes a lingering open session in the same room when a newer join arrives. EndReasonSupersededByRejoin = "superseded_by_rejoin" // EndReasonOrphanLeft closes a session synthesized from a leave fact that arrived before its join fact. EndReasonOrphanLeft = "orphan_left" // CompensationReasonOpenSessionMaxWindow closes open sessions at a configured safety ceiling. CompensationReasonOpenSessionMaxWindow = "compensated_open_session_max_window" ) // RoomPresenceEvent is the decoded room presence fact used by user-service in-room duration aggregation. type RoomPresenceEvent struct { AppCode string EventID string EventType string RoomID string RoomVersion int64 OccurredAtMs int64 // UserID is the presence subject: RoomUserJoined/RoomUserLeft 的 user_id,RoomUserKicked 的 target_user_id。 UserID int64 // IsRobot 只在 RoomUserJoined 上有意义,会话开启时固化,机器人会话不产生统计事实。 IsRobot bool } // ApplyResult describes one idempotent event application. type ApplyResult struct { Consumed bool Skipped bool Opened bool Closed bool Reason string } // CompensationOptions bounds abnormal open sessions so missing leave events cannot accumulate forever. type CompensationOptions struct { NowMs int64 BatchSize int OpenSessionMaxAgeMs int64 } // CompensationResult summarizes one compensation scan. type CompensationResult struct { ClosedCount int OrphanLeavesDeleted int }