bindbox-game/docs/任务中心领取风险审查与测试计划.md
2026-02-27 16:07:12 +08:00

5.6 KiB
Raw Blame History

任务中心领取逻辑风险审查与测试计划

背景与目标

  • 风险点:用户可直接领取、或依赖任务上线前的历史数据领取新的任务奖励,尤其是在 window 未配置或默认 lifetime 的档位上。
  • 目标:明确代码审查要点、需要补强的校验以及自动化/手工测试,确保任务中心的进度统计与领取逻辑默认受限于任务 StartTime ~ EndTime

现状速览

  • 窗口处理normalizeWindow + computeTimeWindow 对非法窗口统一回退 lifetimeWindowActivityPeriod 才会套用任务起止时间(internal/service/task_center/service.go:200-525)。未配置或设置 lifetime 的档位默认统计全部历史。
  • 进度统计GetUserProgress(window, activity_id) 分组统计 TierProgressMap,并回退到全局订单/邀请(service.go:528-668)。
  • 领取校验ClaimTier 先读取 TierProgressMap,再按 metric/operator 判断;含活动的档位使用 Redis tc:claim_lock:{user_id}:{activity_id} 加锁,并做跨任务阈值校验(service.go:670-939)。全局档位没有锁,任务级限额只在总量层面控制。

审查与增强要点

1. 窗口与时间范围

  1. 将“任务设置了 StartTime/EndTime 但 window=空或 lifetime”纳入巡检:建议在 normalizeWindow or GetUserProgress 中,当 task.StartTime 不为空时自动将窗口裁剪到 [StartTime, EndTime],并在单测覆盖空/NULL 窗口场景。
  2. 明确 since_registration 行为:若不允许历史数据,应在 computeTimeWindow 中将起点设为 max(user.RegistrationTime, task.StartTime)
  3. 验证 TierProgressMapSubProgress 是否正确过滤 start_time/end_time:针对 daily/weekly/activity_period/lifetime 构造订单在边界日/周的案例,确保窗口重置与任务期重叠判断符合预期。

2. 领取校验扩展

  1. ClaimTier 中新增“窗口开始 < task.StartTime”判断tierProgress 返回数据完全来自任务上线前,需拒绝并提示“任务尚未开始”或“需重新累计”。
  2. 复核跨任务阈值 calculateCrossTaskConsumedThreshold:目前按任务创建时间 + 窗口重叠过滤,但若 siblingRows 包含旧任务的 lifetime 档位仍可能消耗全部历史,需要配合第 1 点的窗口裁剪。
  3. Redis 锁范围:对于 activity_id=0 的档位,可增加 tc:claim_lock_task:{user_id}:{task_id},防止并发重复领取。

3. 配置与数据守护

  1. 巡检 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 或自定义窗口。
  2. 若需让运营显式配置“允许历史数据”,可在 task_center_task_tiers 增加 allow_legacy_data TINYINT,并在 admin Upsert 接口透出。当前阶段以代码默认裁剪为主。

自动化测试计划

编号 场景 步骤 预期
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 锁 并发触发 ClaimTieractivityID>0 与 activityID=0 场景分别验证 仅一次成功,其余提示“操作频繁”或“已领取”

自动化测试可基于现有 SQLite Repomysql.NewSQLiteRepoForTest)快速构造数据,参考 service_test.goinvite_logic_test.go 的写法。

手工/灰度验证

  1. SQL 巡检:执行上文 SQL导出需要修正的档位配合运营确认并批量更新 window
  2. 模拟接口回放:通过 /admin/task_center/simulate/order_paid/simulate/invite_success 重放旧流水,再调整任务时间并调用 /tasks/{id}/claim/{user},观察日志(ClaimTier: cross-task threshold...任务尚未开始 等)。
  3. 小程序体验:发布新任务后,用老用户登录 pages-user/tasks,确认显示进度清零、领取按钮禁用;完成新订单后刷新 → 按预期解锁。

风险与假设

  • 默认业务需求为“任务上线前的历史数据不可复用”,如需白名单例外需另开配置。
  • Redis/数据库资源允许新增少量锁与巡检脚本,不影响现有性能。
  • 若需要对现网数据批量改 window,需评估是否会影响已经配置为 lifetime 的任务,并提前同步运营。

下一步

  1. 根据本计划完成代码 PoC窗口剪裁、领取校验、锁扩展
  2. 提交自动化测试用例,覆盖表格中的 UT/IT 场景。
  3. 运行 SQL 巡检 + 手工验证,记录整改项。
  4. 如需引入“允许历史数据”配置,评估 schema 与前端/运营端改造影响,再单独立项。