ok
This commit is contained in:
78
plans/is_end派奖结算改造_14ce4dc5.plan.md
Normal file
78
plans/is_end派奖结算改造_14ce4dc5.plan.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
name: is_end派奖结算改造
|
||||
overview: 基于现有 BetFunding/WinService 实现,新增 is_end 分支:中间派奖仅累计不入账,结束派奖统一按 Round Final Settlement 入账;并对中间派奖增加 biz_id 严格幂等。
|
||||
todos:
|
||||
- id: dto-validator-is-end
|
||||
content: 扩展 DTO 与校验器,支持 is_end 并强制 win 场景 round_id 校验
|
||||
status: pending
|
||||
- id: redis-win-keys
|
||||
content: 新增 pending/dedupe Redis key 生成方法与 TTL 约定
|
||||
status: pending
|
||||
- id: logic-win-branching
|
||||
content: 在 WalletLogic::win 中实现 is_end=0 累计与 is_end=1 最终结算分支
|
||||
status: pending
|
||||
- id: idempotency-regression
|
||||
content: 补充关键回归场景说明并验证与现有幂等不冲突
|
||||
status: pending
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# is_end 驱动的派奖结算改造计划
|
||||
|
||||
## 目标
|
||||
让 `win` 接口支持第三方 `is_end` 语义:
|
||||
- `is_end=0`:仅记录/累计本局派奖,不做钱包入账、不做 Lot 终态收敛
|
||||
- `is_end=1`:将本次派奖 + 已累计派奖合并后,执行一次 Final Settlement(现有 `WinService::execute`)
|
||||
|
||||
## 现状结论(基于代码)
|
||||
- 入口路由在 [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php) 的 `type=win -> win()`。
|
||||
- Final Settlement 主流程在 [app/service/wallet/WinService.php](app/service/wallet/WinService.php)。
|
||||
- 当前 `win` 默认即 Final Settlement,不区分中间派奖事件。
|
||||
- 下注资金事实表在 [app/model/multi/WalletBetFundingModel.php](app/model/multi/WalletBetFundingModel.php)。
|
||||
|
||||
## 实现方案(按你选择)
|
||||
### 1) 入参扩展与校验
|
||||
- 在 [app/api/dto/request/wallet/WalletUpdateRequestDTO.php](app/api/dto/request/wallet/WalletUpdateRequestDTO.php) 增加字段:`is_end`(默认 `1`,仅允许 `0|1`)。
|
||||
- 在 [app/validator/Wallet2Validator.php](app/validator/Wallet2Validator.php):
|
||||
- 增加 `is_end` 校验规则(整数且取值 `0/1`)。
|
||||
- 将 `win` 也纳入 `round_id` 必传校验(当前仅 bet 必传)。
|
||||
|
||||
### 2) Redis Key 设计
|
||||
- 在 [app/service/RedisKeyManagerService.php](app/service/RedisKeyManagerService.php) 新增两个 key 生成器:
|
||||
- `wallet:win:pending:{uid}:{currency}:{round_id}`:累计未结算派奖金额
|
||||
- `wallet:win:dedupe:{uid}:{currency}:{round_id}:{biz_id}`:中间派奖幂等标记
|
||||
- 过期策略建议:`pending` 48h,`dedupe` 72h(与重放窗口对齐)。
|
||||
|
||||
### 3) win 主流程分支
|
||||
- 修改 [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php) 的 `win()`:
|
||||
- `is_end=0`:
|
||||
- 命中 dedupe key 则直接返回当前钱包(幂等)
|
||||
- 未命中则将 `fee` 累加到 pending key,写 dedupe key,返回当前钱包(不写 `BIZ_TYPE_WIN` 流水)
|
||||
- `is_end=1`:
|
||||
- 读取 pending 累计并与本次 `fee` 合并为 `finalWinAmount`
|
||||
- 用 `finalWinAmount` 调用现有 `WinService::execute`
|
||||
- 事务提交后清理 pending key(失败不清)
|
||||
|
||||
### 4) 幂等与一致性
|
||||
- `is_end=1` 继续沿用现有 `wallet_log(uid,biz_id,biz_type=win)` 幂等。
|
||||
- `is_end=0` 使用 Redis dedupe key 防重,避免重复累计。
|
||||
- 若 `is_end=1` 无待分配 funding,保持当前行为(报错),便于暴露上游时序问题。
|
||||
|
||||
### 5) 兼容与回归
|
||||
- 默认 `is_end=1`,兼容未传该字段的旧调用。
|
||||
- 回归场景:
|
||||
- 单次结算(只发 `is_end=1`)
|
||||
- 多次派奖(多条 `is_end=0` + 一条 `is_end=1`)
|
||||
- `is_end=0` 重放同 biz_id 不重复累计
|
||||
- `is_end=1` 重放同 biz_id 不重复入账
|
||||
- `is_end=1` 失败后 pending 不丢失
|
||||
|
||||
## 关键改动文件
|
||||
- [app/api/dto/request/wallet/WalletUpdateRequestDTO.php](app/api/dto/request/wallet/WalletUpdateRequestDTO.php)
|
||||
- [app/validator/Wallet2Validator.php](app/validator/Wallet2Validator.php)
|
||||
- [app/service/RedisKeyManagerService.php](app/service/RedisKeyManagerService.php)
|
||||
- [app/api/logic/WalletLogic.php](app/api/logic/WalletLogic.php)
|
||||
|
||||
## 风险与边界
|
||||
- 该方案不新增 `wallet_game_round` / `wallet_game_round_event` 持久化表;中间派奖仅 Redis 暂存,审计粒度弱于 DB 事件流。
|
||||
- 若某局长期无 `is_end=1`,pending 依赖 TTL 过期清理。后续可升级为 DB 事件表方案。
|
||||
Reference in New Issue
Block a user