6.9 KiB
6.9 KiB
幸运礼物重构第三步:链路接入与上线验收
本文档定义幸运礼物重构第三步。第三步把 v2 配置和 v2 抽奖引擎接回房间送礼主链路,完成返奖、IM、后台审计、灰度上线和旧逻辑删除。当前不兼容旧代码,切换完成后旧幸运礼物抽奖入口、旧规则表和旧模拟器都应下线。
目标
| 目标 | 说明 |
|---|---|
| 主链路接入 | room-service 扣费后调用 v2 抽奖 |
| 返奖一致 | activity_outbox 调 wallet-service 入账,钱包 outbox 通知余额 |
| 房间表现一致 | lucky_gift_drawn IM 和区域播报由 outbox 补偿 |
| 后台可审计 | 后台能查 draw、候选表、控制模式、RTP、奖池和风控快照 |
| 可灰度回滚 | 按 pool_id/room_id/region 控制 v2 开关 |
| 删除旧逻辑 | 验收完成后移除旧 v1 抽奖和旧配置入口 |
主链路
Client
-> gateway POST /api/v1/rooms/gift/send
-> room-service 校验房间和目标
-> wallet-service DebitGift
-> room-service 调 activity-service ExecuteLuckyGiftDrawV2
-> activity-service 本地事务写 draw + outbox
-> room-service 落 Room Cell 礼物、热度、榜单
-> gateway 返回 lucky_gift
-> activity worker 返奖入账
-> activity worker 投递 lucky_gift_drawn IM
-> wallet/notice 投递 WalletBalanceChanged
接口要求
App 送礼请求
幸运礼物必须传明确 pool_id:
{
"room_id": "room_1",
"command_id": "cmd_001",
"target_type": "user",
"target_user_ids": [10002],
"gift_id": "lucky_star_100",
"gift_count": 1,
"pool_id": "lucky_100"
}
不再支持“礼物类型是 lucky 但不传 pool_id 时走 default”的隐式路径。
送礼响应
{
"lucky_gift": {
"enabled": true,
"draw_id": "lucky_draw_xxx",
"command_id": "cmd_001",
"pool_id": "lucky_100",
"rule_version": 12,
"stage": "normal",
"control_mode": "normal",
"selected_tier_id": "normal_0_5x",
"multiplier_ppm": 500000,
"base_reward_coins": 50,
"activity_subsidy_coins": 0,
"effective_reward_coins": 50,
"reward_status": "pending",
"created_at_ms": 1779259000000
}
}
客户端规则:
| 场景 | 处理 |
|---|---|
reward_status=pending |
展示中奖结果和“奖励处理中”,不本地加余额 |
收到 WalletBalanceChanged |
更新余额 |
收到同一 draw_id 的 IM |
去重,不重复播放 |
lucky_gift 为空 |
按普通礼物处理 |
outbox 要求
抽奖事务只写事实和 outbox:
| outbox | 作用 |
|---|---|
LuckyGiftRewardCredit |
调钱包返奖 |
LuckyGiftDrawnRoomIM |
投递房间开奖结果 |
LuckyGiftBigWinBroadcast |
投递区域或全站播报 |
顺序要求:
- 先返奖入账。
- 再投递房间开奖结果。
- 最后标记 draw 为
granted。
如果返奖已成功但 IM 失败:
| 状态 | 处理 |
|---|---|
| draw | 不能标记 failed,避免覆盖账务事实 |
| outbox | 继续重试 IM |
| 后台 | 展示“返奖成功,表现补偿中” |
后台审计
后台必须支持:
| 页面 | 能力 |
|---|---|
| 抽奖列表 | 按 pool_id/user_id/room_id/status/control_mode 查询 |
| 抽奖详情 | 展示候选表、过滤原因、权重、随机落点 |
| RTP 看板 | 展示目标 RTP、实际 RTP、控制模式分布 |
| 奖池看板 | 展示 platform / room / gift 水位 |
| 风控看板 | 展示用户、设备、房间、主播过滤次数 |
| outbox 看板 | 展示 pending/retryable/failed |
抽奖详情必须能回答:
为什么这次是 0x?
为什么 100x 被过滤?
为什么进入 boost/cooldown?
这次随机落点在哪里?
返奖是否到账?
房间 IM 是否投递?
灰度策略
| 阶段 | 范围 | 要求 |
|---|---|---|
| shadow | 只计算 v2,不返奖、不发 IM | 和模拟结果接近 |
| internal | 内部房间、小额礼物 | outbox 和钱包稳定 |
| room whitelist | 白名单房间 | 用户体验指标正常 |
| region canary | 单区域小流量 | RTP 和投诉稳定 |
| full | 全量开放 | 旧逻辑可删除 |
灰度开关:
| 开关 | 作用 |
|---|---|
lucky_gift_v2_enabled |
全局 v2 开关 |
pool_v2_enabled |
单奖池开关 |
room_whitelist |
房间白名单 |
region_whitelist |
区域白名单 |
disable_high_tier |
临时关闭高倍 |
reward_credit_enabled |
钱包事故时暂停返奖 dispatch,draw 保持 pending |
监控指标
| 指标 | 告警 |
|---|---|
base_rtp |
超出目标波动带 |
effective_rtp |
高于预算预期 |
zero_rate |
高于配置预期 |
zero_streak_p95 |
超过体验阈值 |
control_mode_boost_ratio |
长期过高说明概率或奖池不健康 |
control_mode_cooldown_ratio |
长期过高说明派奖过多 |
pool_balance_min |
接近 reserve |
risk_filter_count |
过高说明风控在替代概率控制 |
outbox_pending_count |
堆积 |
reward_credit_latency |
到账延迟 |
draw_error_count |
抽奖事务失败 |
旧逻辑删除
全量稳定后删除:
| 旧内容 | 删除条件 |
|---|---|
旧 lucky_gift_rules 写入口 |
v2 后台发布稳定 |
旧 multiplier_ppms -> tiers(weight=0) 归一化 |
v2 引擎全量 |
旧 selectLuckyCandidate 自动权重模型 |
v2 引擎全量 |
旧 tools/lucky-gift-v2-demo 写死倍率模拟 |
新模拟器覆盖 |
空 pool_id 默认奖池路径 |
App 全部传明确 pool_id |
实施任务
- 增加
ExecuteLuckyGiftDrawV2内部接口。 room-service送礼链路改调 v2。- gateway 响应增加
stage/control_mode。 - activity outbox 拆分返奖、房间 IM、区域播报事件。
- 后台增加抽奖详情和候选表审计。
- 增加灰度开关和监控指标。
- shadow draw 跑满一个结算窗口。
- 灰度切流。
- 全量后删除旧逻辑。
验收标准
| 验收项 | 标准 |
|---|---|
| App 参数 | 幸运礼物不传 pool_id 必须拒绝,不走 default |
| 扣费顺序 | 钱包扣费成功后才调用 v2 抽奖 |
| 事务边界 | 抽奖事务内不调用钱包返奖或 IM |
| 同步响应 | lucky_gift 返回 stage/control_mode/multiplier_ppm/reward_status |
| 余额一致 | 客户端余额只由 WalletBalanceChanged 或余额查询更新 |
| outbox 幂等 | 重试不会重复返奖、重复 IM 可由 event_id/draw_id 去重 |
| 后台审计 | 任一 draw 可查看完整候选表和过滤原因 |
| shadow 验证 | shadow 结果的 RTP、命中率、连续 0 分布与模拟报告一致 |
| 灰度指标 | 灰度期间 base RTP 在控制带内,outbox 无持续堆积 |
| 体验指标 | 100 金币礼物 zero_streak_p95 不超过配置阈值 |
| 删除旧逻辑 | 全量稳定后旧配置入口、旧抽奖引擎、旧默认奖池路径已删除 |
| 全量测试 | make test 通过 |
第三步完成后,幸运礼物 v2 才算真正上线。前两步只完成规则和引擎,不能直接对外开放。