// Package store 提供会话存储接口 // 接口解耦使得可以在测试中用 mock 替换,生产用 Redis package store import ( "context" "time" ) // Session 存储的会话数据结构(不含敏感字段) type Session struct { ID string `json:"session_id"` ExpiresAt time.Time `json:"expires_at"` CreatedAt time.Time `json:"created_at"` } // ParticipantInfo 参与者在全量快照中的状态 type ParticipantInfo struct { Nickname string `json:"nickname"` Submitted bool `json:"submitted"` Match *bool `json:"match,omitempty"` } // SessionSnapshot Get 返回的全量快照 type SessionSnapshot struct { SessionID string `json:"session_id"` InitiatorHash string `json:"-"` // 发起方标准答案哈希,不对外暴露 InitiatorNickname string `json:"initiator_nickname"` InitiatorSubmitted bool `json:"initiator_submitted"` AllowResubmit bool `json:"allow_resubmit"` Participants []ParticipantInfo `json:"participants"` ExpiresAt time.Time `json:"expires_at"` } // SessionStore 会话存储接口 type SessionStore interface { // Create 原子创建会话(SET NX EX) Create(ctx context.Context, id string, ttl time.Duration) error // SubmitInitiator 发起方提交标准答案(initiator_hash + initiator_nickname) // 同时立即为所有已提交的参与者计算 match SubmitInitiator(ctx context.Context, sessionID, nickname, hashHex string) error // SubmitParticipant 参与者提交自己的文本(按 nickname 唯一标识) // 返回:initiatorSubmitted(发起方是否已提交,是则 match 已算出)、match SubmitParticipant(ctx context.Context, sessionID, nickname, hashHex string) ( initiatorSubmitted bool, match *bool, err error) // JoinParticipant 参与者加入会话(只登记昵称,不提交文本) // 用于 WS 连接时实时广播 joined 事件 JoinParticipant(ctx context.Context, sessionID, nickname string) error // SetResubmit 设置是否允许参与者重复提交 SetResubmit(ctx context.Context, sessionID string, allow bool) error // Get 获取会话当前状态全量快照 Get(ctx context.Context, sessionID string) (*SessionSnapshot, error) // Delete 删除会话 Delete(ctx context.Context, sessionID string) error }