# 机器人房间技术架构文档 ## 目标 机器人房间提供后台配置驱动的内部房间编排能力,支持机器人创建房间、进房、虚拟静音上麦、普通礼物展示、幸运礼物展示,并保证与真实钱包、真实幸运礼物、真实奖池、真实榜单和结算隔离。 ## 模块边界 ### admin-platform - 提供机器人房间配置页面。 - 调用 admin-server HTTP 接口。 - 不直接访问业务服务。 ### admin-server - 暴露后台 HTTP API。 - 做权限、审计、参数校验和 DTO 转换。 - 通过 gRPC client 调用 room-service 和 robot-service。 - 通过 wallet-service gRPC 获取礼物配置。 - 只读用户库补齐机器人展示资料。 ### robot-service - 只拥有机器人账号池事实。 - 房间机器人池表:`hyapp_robot.robot_room_robots`。 - 不处理进房、麦位、送礼和 IM。 ### room-service - 机器人房间配置 owner。 - 创建真实房间状态。 - 管理机器人房间配置表:`hyapp_room.room_robot_rooms`。 - 执行机器人进房、虚拟静音上麦、送礼循环。 - 强校验机器人送礼仅限同房间机器人。 - 生成机器人幸运礼物展示事件。 ### wallet-service - 只通过 `ListGiftConfigs` 提供 active、区域可用的礼物展示快照。 - `RobotSendGift` 不调用 `DebitRobotGift`,不创建机器人钱包账户、交易、分录或 wallet outbox。 - 礼物目录在 room-service 按 App/区域短缓存;缓存只保存配置,不保存任何送礼事实。 ### activity/statistics - 消费房间送礼事件时跳过 `is_robot_gift`。 - 机器人礼物不进入真实活动、榜单、任务、成长值和统计。 ## 核心数据表 ### `hyapp_robot.robot_room_robots` 机器人账号池事实表。 关键字段: - `app_code` - `room_scene` - `user_id` - `status` - `last_used_at_ms` - `used_count` ### `hyapp_room.room_robot_rooms` 机器人房间配置和占用事实表。 关键字段: - `room_id` - `room_short_id` - `status` - `owner_robot_user_id` - `robot_user_ids_json` - `gift_ids_json` - `lucky_gift_ids_json` - `normal_gift_interval_ms` - `lucky_combo_min` - `lucky_combo_max` - `lucky_pause_min_ms` - `lucky_pause_max_ms` ## 后台 API 后台 HTTP: - `GET /api/v1/admin/rooms/robot-rooms` - `GET /api/v1/admin/rooms/robot-rooms/available-robots` - `POST /api/v1/admin/rooms/robot-rooms` - `POST /api/v1/admin/rooms/robot-rooms/{room_id}/start` - `POST /api/v1/admin/rooms/robot-rooms/{room_id}/stop` room-service gRPC: - `AdminListRobotRooms` - `AdminFilterAvailableRoomRobots` - `AdminCreateRobotRoom` - `AdminSetRobotRoomStatus` wallet-service gRPC: - `ListGiftConfigs`(只读) ## 创建流程 ```mermaid sequenceDiagram participant Admin as admin-platform participant AS as admin-server participant RS as room-service participant RB as robot-service participant DB as MySQL Admin->>AS: POST /admin/rooms/robot-rooms AS->>RS: AdminCreateRobotRoom RS->>DB: 查询 active 机器人房占用 RS->>RS: 从候选机器人随机抽取人数 RS->>RS: CreateRoom(robot_room=true) RS->>RS: JoinRoom for robots RS->>RS: RobotVirtualMicUp for robots RS->>DB: 写 room_robot_rooms RS->>RS: start runtime loops RS-->>AS: AdminRobotRoom AS-->>Admin: 机器人房间详情 ``` ## 运行时循环 room-service 启动时会扫描所有 active 机器人房间并恢复运行时循环。 每个 active 机器人房间: - 为每个机器人启动普通礼物 loop。 - 为每个机器人启动幸运礼物 loop。 - stop 后取消对应房间的 context。 普通礼物 loop: 1. 等待 `normal_gift_interval_ms`。 2. 从 `gift_ids_json` 随机选择礼物。 3. 从同房间其他机器人随机选择 1 个目标。 4. 调用 `RobotSendGift`。 幸运礼物 loop: 1. 从 `lucky_gift_ids_json` 随机选择礼物。 2. 随机生成 `lucky_combo_min-lucky_combo_max` 连击次数。 3. 当前机器人向同房间其他机器人逐个送礼。 4. 使用 `synthetic_lucky_gift=true`,跳过真实抽奖。 5. 等待 `lucky_pause_min_ms-lucky_pause_max_ms` 后继续。 ## 服务端安全校验 room-service 在机器人送礼时强校验: - 专属机器人房必须带 `robot_room=true`;真人房机器人使用运行时机器人池校验,不把真人加入允许集合。 - sender 必须在该机器人房间 `robot_user_ids_json` 内。 - target 必须在同一机器人房间 `robot_user_ids_json` 内。 - sender 不能给真人送礼。 - 当前机器人礼物只允许单目标调用。 ## 纯展示隔离 `RobotSendGift` 不进入通用 `sendGift/mutateRoom`,只执行: 1. 获得或续租 Redis owner lease,并只读当前 Room Cell(缺失时从 MySQL 只读恢复),校验 sender、target 和机器人池。 2. 从 wallet 礼物目录读取并短缓存名称、图标、动画、类型和展示价值。 3. 在内存构造 `RoomGiftSent`;幸运礼物额外构造 `RoomRobotLuckyGiftDrawn`。 4. 经过 2 秒展示采样后,best-effort 直发腾讯云 IM。 这条链路不写 `room_gift_operations`、`room_command_log`、`room_snapshots`、`room_outbox`、房间贡献统计、钱包账本或任何 outbox,也不调用 RocketMQ producer。内存里的 `outbox.Record` 只复用 protobuf 信封结构,不是持久化 outbox。 ## 幸运礼物隔离 机器人幸运礼物不会调用真实幸运抽奖链路。 room-service 只生成展示事件: - `RoomRobotLuckyGiftDrawn` - 对 IM 客户端映射为 `lucky_gift_drawn` - 标记 `synthetic=true` - 携带机器人房间、送礼人、收礼人、礼物和展示金额字段 真实奖池、真实流水、真实返奖、真实统计完全不写入。 ## 排行榜与统计隔离 机器人展示用 `RoomGiftSent` 保留: - `is_robot_gift` - `synthetic_lucky_gift` 该事件不会进入 room outbox/MQ,所以下游活动、CP、任务、成长和 statistics 根本不会收到机器人送礼事实;`is_robot_gift=true` 只供 IM 展示兼容。 机器人送礼同时不修改房间热度、礼物榜、麦位 `gift_value`、火箭燃料、周贡献或 Redis 跨房贡献榜。真人房机器人也遵守同一边界;历史 `RealRoomHeat` 参数仅用于区分参与者校验范围,不能授权真实贡献。 ## 本地接口测试 测试工具: ```bash go run ./tools/robot-room-api-test ``` 默认依赖: - admin-server: `http://127.0.0.1:13100/api/v1` - MySQL: `127.0.0.1:23306` - 管理员账号: `admin / admin123` 工具会: 1. 种 12 个房间机器人账号。 2. 种 2 个礼物配置和价格。 3. 登录 admin-server。 4. 调用可用机器人列表接口。 5. 创建机器人房间。 6. 查询 active 列表。 7. 停止、启动、再次停止机器人房间。 8. 校验 robot 展示前后 `room_gift_operations`、command log、snapshot、room outbox、房间统计行数不变,且 `DebitRobotGift` 调用次数为 0。 ## 运维注意事项 - 多实例 room-service 下,机器人房间 runtime 是进程内循环;重启会从 MySQL active 配置恢复。 - 机器人房间配置以 MySQL 为准。 - 同一机器人账号不能被多个 active 机器人房间占用。 - 停止机器人房间只停止 runtime,不删除房间。 - 如果需要彻底释放机器人账号,应增加删除/归档能力后再开放。 - 腾讯云 IM 是唯一实时展示通道,失败不补写数据库或 MQ,也不重试成业务事实;丢失的动画/公屏不恢复,房间快照只保证真实热度、榜单和麦位值不被机器人展示污染。