2026-04-25 01:18:30 +08:00

196 lines
6.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package command 定义 room-service 可持久化、可回放的房间命令模型。
package command
import "encoding/json"
// Command 统一表达可写入 command log 的房间命令。
type Command interface {
// ID 返回命令幂等键,通常来自 gateway 的 RequestMeta.command_id。
ID() string
// RoomID 返回命令所属房间Room Cell 路由和 command log 分区依赖它。
RoomID() string
// ActorUserID 返回命令操作者,不能由具体命令字段重复推导。
ActorUserID() int64
// Type 返回稳定命令类型,持久化和恢复反序列化都依赖该字符串。
Type() string
}
// Base 承载所有房间命令都共享的元信息。
type Base struct {
// RequestID 是入口请求 ID用于追踪一次外部调用。
RequestID string `json:"request_id"`
// CommandID 是幂等主键,重复命令必须返回已提交状态而不是重复变更房间。
CommandID string `json:"command_id"`
// ActorID 是操作者用户 ID房间权限和 presence 校验以它为准。
ActorID int64 `json:"actor_user_id"`
// Room 是目标房间 ID命令只允许作用于一个 Room Cell。
Room string `json:"room_id"`
// GatewayNodeID 记录入口节点,便于排查命令来源。
GatewayNodeID string `json:"gateway_node_id"`
// SessionID 记录 gateway 看到的客户端会话,不等同于 im-service WebSocket 连接。
SessionID string `json:"session_id"`
// SentAtMS 是客户端请求进入系统的时间,恢复回放时用于还原用户态时间字段。
SentAtMS int64 `json:"sent_at_ms"`
}
// ID 返回命令幂等主键。
func (b Base) ID() string {
return b.CommandID
}
// RoomID 返回命令所属房间。
func (b Base) RoomID() string {
return b.Room
}
// ActorUserID 返回命令操作者。
func (b Base) ActorUserID() int64 {
return b.ActorID
}
// CreateRoom 定义房间创建请求。
type CreateRoom struct {
Base
// OwnerUserID 是房间所有者,创建后自动进入管理员集合。
OwnerUserID int64 `json:"owner_user_id"`
// HostUserID 是主持人,创建后也进入管理员集合。
HostUserID int64 `json:"host_user_id"`
// SeatCount 决定初始化麦位数量。
SeatCount int32 `json:"seat_count"`
// Mode 记录房间模式,当前版本只保存不做复杂策略分发。
Mode string `json:"mode"`
}
// Type 返回命令类型。
func (CreateRoom) Type() string { return "create_room" }
// JoinRoom 定义业务进房请求。
type JoinRoom struct {
Base
// Role 是用户在房间内的轻量角色,默认 audience。
Role string `json:"role"`
}
// Type 返回命令类型。
func (JoinRoom) Type() string { return "join_room" }
// LeaveRoom 定义业务离房请求。
type LeaveRoom struct {
Base
}
// Type 返回命令类型。
func (LeaveRoom) Type() string { return "leave_room" }
// MicUp 定义上麦请求。
type MicUp struct {
Base
// SeatNo 是目标麦位编号,从 RoomState 初始化的麦位集合中查找。
SeatNo int32 `json:"seat_no"`
}
// Type 返回命令类型。
func (MicUp) Type() string { return "mic_up" }
// MicDown 定义下麦请求。
type MicDown struct {
Base
// TargetUserID 是被下麦用户;操作者和目标用户可以不同。
TargetUserID int64 `json:"target_user_id"`
}
// Type 返回命令类型。
func (MicDown) Type() string { return "mic_down" }
// ChangeMicSeat 定义换麦位请求。
type ChangeMicSeat struct {
Base
// TargetUserID 是需要换位的用户。
TargetUserID int64 `json:"target_user_id"`
// SeatNo 是目标麦位编号。
SeatNo int32 `json:"seat_no"`
}
// Type 返回命令类型。
func (ChangeMicSeat) Type() string { return "change_mic_seat" }
// MuteUser 定义禁言请求。
type MuteUser struct {
Base
// TargetUserID 是被修改禁言状态的用户。
TargetUserID int64 `json:"target_user_id"`
// Muted 为 true 表示禁言false 表示解除禁言。
Muted bool `json:"muted"`
}
// Type 返回命令类型。
func (MuteUser) Type() string { return "mute_user" }
// KickUser 定义踢人请求。
type KickUser struct {
Base
// TargetUserID 是被踢出并加入 ban 集合的用户。
TargetUserID int64 `json:"target_user_id"`
}
// Type 返回命令类型。
func (KickUser) Type() string { return "kick_user" }
// SendGift 定义送礼请求。
type SendGift struct {
Base
// TargetUserID 是礼物接收方,当前版本要求接收方在房间内。
TargetUserID int64 `json:"target_user_id"`
// GiftID 是礼物配置标识,具体配置有效性当前由调用方和 wallet 链路保证。
GiftID string `json:"gift_id"`
// GiftCount 是礼物数量,必须为正数。
GiftCount int32 `json:"gift_count"`
// GiftUnitValue 是单个礼物价值,必须为正数,账务扣费由 wallet-service 执行。
GiftUnitValue int64 `json:"gift_unit_value"`
}
// Type 返回命令类型。
func (SendGift) Type() string { return "send_gift" }
// Serialize 把命令编码成 command log 持久化所需的稳定载荷。
func Serialize(cmd Command) ([]byte, error) {
// 当前 command log 使用 JSON 载荷,便于排查;命令类型由独立列保存。
return json.Marshal(cmd)
}
// Deserialize 按命令类型恢复命令载荷。
func Deserialize(commandType string, payload []byte) (Command, error) {
var cmd Command
// command_type 是恢复时的分发键,未知命令返回 nil 让恢复流程安全跳过。
switch commandType {
case CreateRoom{}.Type():
cmd = &CreateRoom{}
case JoinRoom{}.Type():
cmd = &JoinRoom{}
case LeaveRoom{}.Type():
cmd = &LeaveRoom{}
case MicUp{}.Type():
cmd = &MicUp{}
case MicDown{}.Type():
cmd = &MicDown{}
case ChangeMicSeat{}.Type():
cmd = &ChangeMicSeat{}
case MuteUser{}.Type():
cmd = &MuteUser{}
case KickUser{}.Type():
cmd = &KickUser{}
case SendGift{}.Type():
cmd = &SendGift{}
default:
return nil, nil
}
if err := json.Unmarshal(payload, cmd); err != nil {
// 单条命令反序列化失败说明 command log 损坏,恢复流程必须失败而不是继续构建错误状态。
return nil, err
}
return cmd, nil
}