13 KiB
🚀 语聊房火箭系统 - 完整需求文档
📋 文档信息
| 项目 | 内容 |
|---|---|
| 文档名称 | 语聊房火箭系统需求文档 |
| 版本 | v1.0 |
| 创建日期 | 2025-01-15 |
| 所属项目 | Likei Services |
| 所属模块 | rc-service-other |
| 项目路径 | D:\workspace\likei-services\rc-service\rc-service-other |
1. 业务需求
1.1 功能概述
语聊房火箭是一个房间级互动玩法,用户通过送礼积累火箭能量,达到阈值后自动发射并分发奖励。
1.2 核心规则
能量积累规则
- 基础规则:1金币礼物 = 1火箭能量点
- 幸运加成:幸运礼物额外增加4%能量
- 实时累积:每次送礼立即增加能量
火箭等级系统
| 等级 | 能量阈值 | 说明 |
|---|---|---|
| Lv1 | 150,000 | 一级火箭 |
| Lv2 | 500,000 | 二级火箭 |
| Lv3 | 1,000,000 | 三级火箭 |
发射机制
- 能量达到阈值自动触发发射
- 发射后进入"领取中"状态
- 领取有效期:1分钟
奖励领取规则
- 房间内所有用户可领取
- 贡献者和普通用户奖励不同(配置待定)
- 每人限领一次
- 过期后自动重置
每日重置
- 每天00:00重置火箭状态
- 历史记录保存到MongoDB
2. 技术架构
2.1 技术栈
| 组件 | 技术 |
|---|---|
| 语言 | Java 17+ |
| 框架 | Spring Boot |
| 数据库 | MySQL + MongoDB |
| 缓存 | Redis |
| 架构模式 | DDD + CQRS |
2.2 数据库设计
MongoDB 集合
room_rocket_status - 火箭实时状态
{
"_id": ObjectId,
"room_id": NumberLong,
"date": "2025-01-15",
"level": 1, // 1/2/3
"current_energy": NumberLong(85000),
"max_energy": NumberLong(150000),
"status": 1, // 1:CHARGING 2:LAUNCHED 3:CLAIMING
"contributors": [
{
"user_id": NumberLong,
"user_name": "张三",
"user_avatar": "https://...",
"energy": NumberLong(50000),
"contribution_rate": 58.82,
"gift_count": 125,
"first_contribute_time": ISODate,
"last_contribute_time": ISODate
}
],
"launch_time": ISODate,
"claim_expire_time": ISODate,
"claim_count": 0,
"created_at": ISODate,
"updated_at": ISODate
}
// 索引
db.room_rocket_status.createIndex({"room_id": 1, "date": 1}, {unique: true})
db.room_rocket_status.createIndex({"status": 1})
MySQL 表
rocket_config - 火箭配置表
CREATE TABLE `rocket_config` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`level` TINYINT UNSIGNED NOT NULL COMMENT '等级 1/2/3',
`max_energy` BIGINT UNSIGNED NOT NULL COMMENT '最大能量值',
`reward_config` JSON DEFAULT NULL COMMENT '奖励配置(预留)',
`status` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_level` (`level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `rocket_config` (`level`, `max_energy`) VALUES
(1, 150000),
(2, 500000),
(3, 1000000);
rocket_reward_claim_log - 奖励领取记录表
CREATE TABLE `rocket_reward_claim_log` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`rocket_history_id` VARCHAR(32) NOT NULL COMMENT 'MongoDB _id',
`room_id` BIGINT UNSIGNED NOT NULL,
`user_id` BIGINT UNSIGNED NOT NULL,
`is_contributor` TINYINT UNSIGNED NOT NULL COMMENT '是否贡献者',
`reward_type` VARCHAR(32) NOT NULL COMMENT 'GOLD/DIAMOND/PROP',
`reward_amount` BIGINT UNSIGNED NOT NULL,
`claimed_at` DATETIME NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rocket_user` (`rocket_history_id`, `user_id`),
KEY `idx_room_id` (`room_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.3 Redis 缓存设计
| Key | 类型 | TTL | 用途 |
|---|---|---|---|
| ROCKET:STATUS:{roomId} | String(JSON) | 24h | 状态缓存 |
| ROCKET:LOCK:{roomId} | String | 5s | 分布式锁 |
| ROCKET:CLAIMED:{historyId} | Set | 2min | 已领取用户 |
| ROCKET:CONFIG:{level} | String(JSON) | 1h | 配置缓存 |
3. 核心流程
3.1 能量积累流程
用户送礼 → GiftSendEvent
↓
RocketEnergyAddCmdExe
↓
1. 获取分布式锁 (Redis)
2. 查询火箭状态 (MongoDB)
3. 计算能量值 (普通/幸运)
4. 更新能量和贡献者
5. 检查等级提升
6. 保存状态
7. 判断是否达到发射条件
├─ 是 → 触发发射
└─ 否 → 推送能量更新
3.2 火箭发射流程
能量达到阈值
↓
RocketLaunchCmdExe
↓
1. 获取分布式锁
2. 校验状态和能量
3. 发射火箭 (status → LAUNCHED)
4. 设置领取过期时间 (+1分钟)
5. 进入领取状态 (status → CLAIMING)
6. 保存状态
7. 推送发射动画 (TODO: WebSocket)
8. 保存历史记录 (TODO)
3.3 奖励领取流程
用户点击领取
↓
RocketRewardClaimCmdExe
↓
1. 获取分布式锁
2. 校验领取资格
├─ 状态是否为CLAIMING
├─ 是否过期
└─ 是否重复领取
3. 判断是否贡献者
4. 计算奖励金额 (TODO: 配置)
5. 调用钱包服务发放 (TODO)
6. 记录领取日志 (MySQL)
7. 更新领取人数
8. 返回奖励详情
3.4 每日重置流程
定时任务 00:00
↓
RocketDailyResetTask
↓
1. 查询所有CHARGING状态火箭
2. 保存历史记录 (TODO)
3. 重置火箭状态
├─ level = 1
├─ current_energy = 0
├─ contributors = []
└─ date = 今天
4. 清除Redis缓存
4. API 接口设计
4.1 查询火箭状态
接口: GET /api/rocket/status
请求参数:
{
"roomId": 123456,
"currentUserId": 789 // 可选
}
响应数据:
{
"roomId": 123456,
"date": "2025-01-15",
"level": 2,
"levelName": "二级火箭",
"currentEnergy": 350000,
"maxEnergy": 500000,
"energyPercent": 70.00,
"status": "CHARGING",
"statusDesc": "充能中",
"topContributors": [
{
"userId": 789,
"userName": "张三",
"userAvatar": "https://...",
"energy": 200000,
"contributionRate": 57.14,
"rank": 1,
"giftCount": 500
}
],
"totalContributors": 25,
"claimCount": 0,
"canClaim": false,
"hasClaimed": false,
"myContribution": 200000,
"myContributionRate": 57.14
}
4.2 领取奖励
接口: POST /api/rocket/claim
请求参数:
{
"roomId": 123456,
"userId": 789,
"rocketHistoryId": "507f1f77bcf86cd799439011"
}
响应数据:
{
"rewardType": "GOLD",
"rewardAmount": 1000,
"isContributor": true,
"contributionEnergy": 200000,
"contributionRate": 57.14,
"message": "恭喜您获得贡献者奖励!"
}
4.3 手动触发发射 (测试用)
接口: POST /api/rocket/manual-launch
请求参数:
roomId=123456
5. 已实现文件清单
5.1 Domain 层
✅ RocketLevel.java - 等级枚举
✅ RocketStatusEnum.java - 状态枚举
✅ RocketContributor.java - 贡献者值对象
✅ RocketStatus.java - 火箭状态领域对象
✅ RocketStatusGateway.java - Gateway接口
5.2 Infrastructure 层
✅ RocketKeys.java - Redis Key枚举
✅ RocketStatusDocument.java - MongoDB文档
✅ RocketStatusRepository.java - MongoDB Repository
✅ RocketStatusGatewayImpl.java - Gateway实现
5.3 Client 层
✅ RocketEnergyAddCmd.java - 能量增加命令
✅ RocketRewardClaimCmd.java - 奖励领取命令
✅ RocketStatusQueryCmd.java - 状态查询命令
✅ RocketStatusCO.java - 状态客户端对象
✅ RocketContributorCO.java - 贡献者客户端对象
✅ RocketRewardCO.java - 奖励客户端对象
✅ RocketService.java - 服务接口
5.4 Application 层
✅ RocketEnergyAddCmdExe.java - 能量增加执行器
✅ RocketLaunchCmdExe.java - 火箭发射执行器
✅ RocketStatusQryExe.java - 状态查询执行器
✅ RocketRewardClaimCmdExe.java - 奖励领取执行器
✅ RocketServiceImpl.java - 服务实现
✅ RocketDailyResetTask.java - 每日重置任务
✅ RocketClaimExpireTask.java - 过期检查任务
5.5 Adapter 层
✅ RocketRestController.java - REST控制器
6. 待实现功能清单
6.1 高优先级 (P0)
1. 礼物事件监听
文件: GiftSendRocketListener.java
位置: other-application/src/.../app/listener/
功能: 监听送礼事件,自动触发能量增加
@EventListener
public void onGiftSend(GiftSendEvent event) {
RocketEnergyAddCmd cmd = new RocketEnergyAddCmd();
cmd.setRoomId(event.getRoomId());
cmd.setUserId(event.getUserId());
cmd.setGiftGoldValue(event.getGiftGoldValue());
cmd.setIsLucky(event.getIsLuckyGift());
cmd.setBizNo("GIFT_" + event.getGiftOrderId());
rocketService.addEnergy(cmd);
}
2. MySQL 表创建
执行SQL:
rocket_config配置表rocket_reward_claim_log领取记录表
3. MongoDB 索引创建
db.room_rocket_status.createIndex(
{"room_id": 1, "date": 1},
{unique: true, name: "uk_room_date"}
)
db.room_rocket_status.createIndex(
{"status": 1},
{name: "idx_status"}
)
4. 奖励发放集成
需要: 调用 wallet-inner-api
实现: 在 RocketRewardClaimCmdExe 中补充
// 注入 Feign Client
@Autowired
private WalletGoldClient walletGoldClient;
// 发放奖励
String bizNo = "ROCKET_" + rocketHistoryId + "_" + userId;
WalletReceiptReqDTO req = new WalletReceiptReqDTO();
req.setUserId(userId);
req.setAmount(rewardAmount);
req.setBizType(WalletBizType.ROCKET_REWARD);
req.setBizNo(bizNo);
walletGoldClient.income(req);
5. 领取防重实现
实现: MySQL唯一索引 + Redis检查
// 查询MySQL
boolean hasClaimed = rocketRewardLogGateway.existsByRocketAndUser(
rocketHistoryId, userId
);
if (hasClaimed) {
throw new RuntimeException("您已经领取过奖励了");
}
6.2 中优先级 (P1)
6. 历史记录保存
文件: RocketHistoryDocument.java + RocketHistoryRepository.java
功能: 发射后保存完整历史
7. WebSocket 推送
功能:
- 能量更新推送
- 发射动画推送
- 领取通知推送
8. 奖励配置管理
功能: 后台配置各等级奖励规则
9. 排行榜查询
文件: RocketRankingQryExe.java
功能: 查询贡献排行榜
6.3 低优先级 (P2)
10. 管理后台接口
功能:
- 配置管理
- 数据统计
- 手动重置
11. 数据统计报表
功能: 发射次数、领取人数等统计
12. 监控告警
功能: 关键指标监控、异常告警
7. 测试用例
7.1 单元测试
@Test
public void testEnergyAdd_Normal() {
// 正常送礼增加能量
}
@Test
public void testEnergyAdd_Lucky() {
// 幸运礼物增加能量
}
@Test
public void testRocketLaunch_AutoTrigger() {
// 能量满自动发射
}
@Test
public void testRewardClaim_Contributor() {
// 贡献者领取奖励
}
@Test
public void testRewardClaim_Duplicate() {
// 重复领取防重
}
7.2 集成测试场景
- 完整流程: 送礼 → 发射 → 领取
- 并发送礼: 100人同时送礼
- 分布式锁: 高并发下的锁测试
- 过期重置: 领取过期自动重置
8. 部署说明
8.1 环境要求
- MongoDB 4.4+
- MySQL 8.0+
- Redis 6.0+
8.2 配置示例
# application.yml
spring:
data:
mongodb:
uri: mongodb://localhost:27017/likei
datasource:
url: jdbc:mysql://localhost:3306/likei
username: root
password: password
rocket:
enabled: true
lucky-bonus-rate: 0.04
claim-expire-seconds: 60
8.3 启动顺序
- 启动 MongoDB
- 启动 MySQL
- 启动 Redis
- 执行数据库初始化脚本
- 启动应用
9. 注意事项
9.1 幂等性
- 能量增加使用
bizNo防重 - 奖励领取使用 MySQL 唯一索引防重
9.2 并发控制
- 使用 Redis 分布式锁
- 锁粒度:房间级别
9.3 数据一致性
- MongoDB 保存实时状态
- MySQL 保存领取记录
- 通过业务逻辑保证一致性
9.4 性能优化
- 热点房间使用 Redis 缓存
- 批量查询贡献者
- 异步推送消息
d
10. 联系方式
技术支持: system
文档维护: Leo
最后更新: 2025-01-15
附录:快速上手指南
A. 快速测试流程
- 初始化数据库
-- 执行 MySQL 建表语句
-- 插入火箭配置数据
- 创建 MongoDB 索引
use likei
db.room_rocket_status.createIndex({"room_id": 1, "date": 1}, {unique: true})
- 启动应用
cd other-start
mvn spring-boot:run
- 测试接口
# 查询状态
curl "http://localhost:8080/api/rocket/status?roomId=123456"
# 手动发射 (测试用)
curl -X POST "http://localhost:8080/api/rocket/manual-launch?roomId=123456"
# 领取奖励
curl -X POST "http://localhost:8080/api/rocket/claim" \
-H "Content-Type: application/json" \
-d '{"roomId":123456,"userId":789,"rocketHistoryId":"xxx"}'
B. 常见问题
Q: 如何手动触发能量增加?
A: 调用 RocketService.addEnergy(cmd) 或监听送礼事件
Q: 如何查看当前火箭状态?
A: 访问 MongoDB room_rocket_status 集合或调用查询接口
Q: 如何重置火箭? A: 等待每日00:00自动重置,或手动调用重置方法
祝开发顺利!🚀