5.6 KiB
5.6 KiB
任务中心领取逻辑风险审查与测试计划
背景与目标
- 风险点:用户可直接领取、或依赖任务上线前的历史数据领取新的任务奖励,尤其是在
window未配置或默认lifetime的档位上。 - 目标:明确代码审查要点、需要补强的校验以及自动化/手工测试,确保任务中心的进度统计与领取逻辑默认受限于任务
StartTime ~ EndTime。
现状速览
- 窗口处理:
normalizeWindow+computeTimeWindow对非法窗口统一回退lifetime,WindowActivityPeriod才会套用任务起止时间(internal/service/task_center/service.go:200-525)。未配置或设置lifetime的档位默认统计全部历史。 - 进度统计:
GetUserProgress按(window, activity_id)分组统计TierProgressMap,并回退到全局订单/邀请(service.go:528-668)。 - 领取校验:
ClaimTier先读取TierProgressMap,再按 metric/operator 判断;含活动的档位使用 Redistc:claim_lock:{user_id}:{activity_id}加锁,并做跨任务阈值校验(service.go:670-939)。全局档位没有锁,任务级限额只在总量层面控制。
审查与增强要点
1. 窗口与时间范围
- 将“任务设置了
StartTime/EndTime但 window=空或lifetime”纳入巡检:建议在normalizeWindoworGetUserProgress中,当task.StartTime不为空时自动将窗口裁剪到[StartTime, EndTime],并在单测覆盖空/NULL 窗口场景。 - 明确
since_registration行为:若不允许历史数据,应在computeTimeWindow中将起点设为max(user.RegistrationTime, task.StartTime)。 - 验证
TierProgressMap、SubProgress是否正确过滤start_time/end_time:针对daily/weekly/activity_period/lifetime构造订单在边界日/周的案例,确保窗口重置与任务期重叠判断符合预期。
2. 领取校验扩展
- 在
ClaimTier中新增“窗口开始 < task.StartTime”判断:若tierProgress返回数据完全来自任务上线前,需拒绝并提示“任务尚未开始”或“需重新累计”。 - 复核跨任务阈值
calculateCrossTaskConsumedThreshold:目前按任务创建时间 + 窗口重叠过滤,但若siblingRows包含旧任务的lifetime档位仍可能消耗全部历史,需要配合第 1 点的窗口裁剪。 - Redis 锁范围:对于
activity_id=0的档位,可增加tc:claim_lock_task:{user_id}:{task_id},防止并发重复领取。
3. 配置与数据守护
- 巡检 SQL(示例):
对结果逐条评估是否需改成SELECT tiers.id, tiers.task_id, tiers.window, tasks.start_time, tasks.end_time FROM task_center_task_tiers tiers JOIN task_center_tasks tasks ON tasks.id = tiers.task_id WHERE (tiers.window IS NULL OR tiers.window = '' OR tiers.window = 'lifetime') AND tasks.start_time IS NOT NULL;activity_period或自定义窗口。 - 若需让运营显式配置“允许历史数据”,可在
task_center_task_tiers增加allow_legacy_data TINYINT,并在adminUpsert 接口透出。当前阶段以代码默认裁剪为主。
自动化测试计划
| 编号 | 场景 | 步骤 | 预期 |
|---|---|---|---|
| UT-1 | lifetime + StartTime 剪裁 |
任务 StartTime=T0,插入 T0-1/T0+1 订单,调用 GetUserProgress |
仅统计 T0+1 数据;TierProgressMap 中的数量=1 |
| UT-2 | 空 Window | 档位 window='',任务 StartTime=T0,同上 |
行为等同 UT-1 |
| UT-3 | since_registration |
构造用户注册时间 Treg < T0,验证窗口起点为 max(Treg, T0) |
统计以 T0 为准 |
| IT-1 | 历史数据领取阻断 | 先插入历史订单,使 TierProgressMap 达标;上线任务后 ClaimTier |
返回“任务条件未达成” |
| IT-2 | 新订单后可领 | 在 IT-1 基础上插入新订单超过阈值再 ClaimTier |
领取成功 |
| IT-3 | 跨任务占用 | 旧任务(已领 50 单) + 新任务阈值 60 单,新订单 15 单 | ClaimTier 拒绝,日志输出 cross-task threshold;再补 10 单 → 成功 |
| IT-4 | Redis 锁 | 并发触发 ClaimTier;activityID>0 与 activityID=0 场景分别验证 |
仅一次成功,其余提示“操作频繁”或“已领取” |
自动化测试可基于现有 SQLite Repo(
mysql.NewSQLiteRepoForTest)快速构造数据,参考service_test.go、invite_logic_test.go的写法。
手工/灰度验证
- SQL 巡检:执行上文 SQL,导出需要修正的档位,配合运营确认并批量更新
window。 - 模拟接口回放:通过
/admin/task_center/simulate/order_paid、/simulate/invite_success重放旧流水,再调整任务时间并调用/tasks/{id}/claim/{user},观察日志(ClaimTier: cross-task threshold...、任务尚未开始等)。 - 小程序体验:发布新任务后,用老用户登录
pages-user/tasks,确认显示进度清零、领取按钮禁用;完成新订单后刷新 → 按预期解锁。
风险与假设
- 默认业务需求为“任务上线前的历史数据不可复用”,如需白名单例外需另开配置。
- Redis/数据库资源允许新增少量锁与巡检脚本,不影响现有性能。
- 若需要对现网数据批量改
window,需评估是否会影响已经配置为lifetime的任务,并提前同步运营。
下一步
- 根据本计划完成代码 PoC(窗口剪裁、领取校验、锁扩展)。
- 提交自动化测试用例,覆盖表格中的 UT/IT 场景。
- 运行 SQL 巡检 + 手工验证,记录整改项。
- 如需引入“允许历史数据”配置,评估 schema 与前端/运营端改造影响,再单独立项。