Files
junhong_cmp_fiber/openspec/changes/reliable-order-commission-dispatch/design.md
break 7e7f1cbb67
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 53s
更新
2026-08-13 16:09:38 +08:00

57 lines
3.7 KiB
Markdown
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.
## Context
当前订单服务在事务提交后直接向 Asynq 提交 `commission:calculate`;退款服务在审批事务提交后使用裸 goroutine 回扣佣金及处理资产。两者均不与业务事实绑定进程、Redis 或 Worker 短暂异常会分别遗留待计算订单或 `commission_deducted=false` 的已退款单。现有 Outbox 已具备状态、租约、重试与任务投递能力;见 proposal.md。
## Goals / Non-Goals
**Goals:**
- 将订单佣金计算请求纳入现有 Outbox 可靠投递链路。
- 为遗留待计算订单提供有界、幂等的补偿入口。
- 为遗留退款后处理提供有界、幂等的补偿入口。
- 保持现有佣金计算与订单结果兼容。
**Non-Goals:**
- 不改变佣金金额、分配规则或提现逻辑。
- 不引入新队列、中间件或外部依赖。
- 不自动修改已完成、待人工修正或未支付订单。
- 不改变退款金额、审批结论和既有资产后处理业务规则。
## Decisions
### 使用订单级稳定事件 ID 写入现有 Outbox
订单创建/支付成功的同一数据库事务写入 `order.commission.calculate` 事件,业务键由订单 ID 派生,建立唯一约束或既有去重语义。选择 Outbox 而不是事务后重试 Asynq因为事件能与已支付订单原子落库并具备失败状态。
### Relay 投递现有佣金任务类型
新增 Outbox 消费者仅将结构化订单 ID 投递给既有 `commission:calculate`,不改佣金计算服务。选择复用任务处理器,避免并行的计算实现和金额语义分叉。
### 有界扫描补偿历史待计算订单
Worker 启动或既有调度器以分页上限扫描已支付、`CommissionStatusPending` 的订单;缺事件或终态失败事件时按同一业务键补写/恢复事件。选择可重复扫描而非一次性数据库修复,方便部署中断恢复;扫描只恢复投递,不直接计算。
### 退款后处理使用退款单级 Outbox 事件
退款审批成功的同一事务分别写入佣金回扣与资产后处理事件,业务键按退款单和处理类型派生。消费者调用既有幂等后处理函数。选择两个独立事件以保留“佣金已回扣但资产重置待处理”的现有可观察状态;不把长资产操作放进审批事务。
### 有界扫描补偿已退款未完成单
Worker 按分页上限扫描已退款且 `commission_deducted=false``asset_reset=false` 的退款单,并按稳定业务键恢复缺失或终态失败事件。选择状态驱动扫描而非单次修数,确保已退款订单在部署或 Worker 中断后仍可恢复。
### 以既有终态判断实现消费幂等
佣金服务已对已完成和待人工修正订单跳过。补偿和消费者只产生同一业务键事件,佣金记录仍由现有计算事务落库,防止重复余额发放。
## Risks / Trade-offs
- [同一订单存在旧直投与新 Outbox 任务] → 依赖既有佣金终态短路和记录事务,部署期间允许重复请求。
- [补偿扫描加载过多历史数据] → 固定批量上限、按状态和支付状态筛选,并输出扫描计数与失败日志。
- [事件定义/消费者漏注册] → Worker 启动时注册并在构建与手工测试中验证事件由 Relay 投递。
- [退款审批与旧 goroutine 并发] → 新事件和既有回扣函数均以退款标记、佣金状态与回扣流水去重,部署过渡允许重复请求。
## Migration Plan
1. 先发布带事件类型、消费者和补偿扫描的新 Worker/API 版本。
2. 部署后执行订单与退款补偿扫描,核对待计算订单、已退款未回扣退款单、投递状态及资金结果。
3. 若需回滚代码,停止补偿扫描;已持久化事件保留,恢复新版本后继续投递,不回滚订单、退款或佣金事实。