Files
zt-closet-backend/docs/code-review-2026-09-15.md
2026-09-15 16:02:45 +08:00

4.5 KiB
Raw Permalink Blame History

代码审查与修复记录(2026-09-15)

本轮检查覆盖登录鉴权、普通支付、虚拟支付、退款与补偿、会员和额度、上传与异步处理、AI 推荐、穿搭、衣柜分享、收藏点赞及通知。已运行全仓库 go test ./... 与 go vet ./...。未连接生产数据库,也未发起真实支付、退款或外部模型调用。

已修复

  1. 同一用户续费同一会员包重复赠送额度

    • 会员额度发放在用户行锁内按 user_id + goods_id + quota_type 检查历史凭证。
    • 首购发放,续费只延长会员时间,不追加或重置额度;不同会员商品与加量包仍按各自规则处理。
    • 历史重复数据不自动回收,使用 scripts/audit_member_quota_duplicates.sql 先盘点。
  2. 退款完成后权益回收失败无法恢复

    • 新增 benefit_revoke_tasks。订单退款终态、待发放任务取消和回收任务创建在同一事务完成。
    • 回收立即尝试,并由定时任务持续幂等重试;超过常规告警阈值后仍继续,避免永久遗漏。
    • 退款回调即使退款流水已成功,也会继续核对订单和回收任务。
  3. 退款与权益发放竞态

    • 发放任务执行前锁定订单并确认仍为已支付状态。
    • 退款事务取消待处理任务;已在执行的任务与退款按订单锁串行,退款随后回收已发权益。
  4. VIP 开通/续费幂等键不稳定

    • 在用户锁内按订单号检查全部购买类 VIP 流水,再根据锁内旧状态确定开通或续费类型。
    • 同一订单重试时不会因 change_type 从开通变成续费而重复增加会员天数。
  5. 广告奖励可无限更换 ref_id 领取

    • 新增单用户、单奖励类型每日领取上限 AdReward.MaxClaimsPerDay,默认 1。
    • 用户锁内完成当日计数校验、事件幂等、额度凭证和流水写入。
    • 当前仓库没有广告平台服务端核验接口,因此本次用服务端每日硬上限消除无限领取;以后接入可信回调时,应再校验广告事件凭证。
  6. 已支付订单缺少权益任务时永久遗漏

    • 补偿调度会扫描已支付但权益任务不完整的订单,补建任务并走统一幂等发放路径。
  7. 每日额度重复计数、失败回退不对称、Redis 丢键重置

    • 删除业务成功后的第二次计数。
    • MySQL user_daily_usages 改为每日额度权威账本,通过条件更新原子校验上限。
    • Redis 仅作缓存;消费与回退后删除缓存,Redis 丢键不会重新放出额度。
  8. 图片任务超时或重启后卡住

    • 建衣物记录前持久化原图路径;成功、失败或删除后清理文件。
    • 失败状态与额度回退使用独立短超时上下文,不受主处理 context 超时影响。
    • 新增超时任务原子认领与每分钟恢复调度,多实例不会重复认领同一任务。
  9. 收到的穿搭分享在取消或转私后仍泄露内容

    • 接收列表联查分享和穿搭,仅返回分享正常、穿搭公开、审核通过且状态正常的记录。
    • ⚠️ 后续策略变更(见 接口文档.md §5.8):「分享给好友」与「公开到社区」已解耦,仅自己可见的穿搭同样可分享;接收列表与分享详情改为只排除已删除 / 已封禁的穿搭,不再按 is_public / audit_status 过滤。此处"转私后不再下发"的旧结论已作废,请勿据此回退代码。
  10. 穿搭、AI 穿搭和衣柜分享的主记录与明细非事务写入

    • 创建、更新重建明细和删除统一使用数据库事务,明细失败时主记录一并回滚。
  11. 权益依赖实时商品配置

    • 订单新增 goods_type 与 quota_valid_days 快照,普通支付与虚拟支付下单时写入,发放时读取订单快照。
    • 迁移会为历史订单从商品表回填;未回填的历史记录保留兼容读取路径,读取失败会进入补偿重试。

按要求暂缓

  1. 虚拟支付公开回调无限制读取请求体:internal/routers/api/v1/order.go:177。
  2. 令牌刷新并发与同秒重复问题:internal/service/user.go:280、pkg/lzcwyjwt/lzcwyjwt.go:30。

上线事项

  • 先执行数据库迁移 000020_harden_benefit_workflows.up.sql,再发布新代码。
  • 配置 AdReward.MaxClaimsPerDay;缺省或非正数时服务按 1 处理。
  • 测试库应验证普通支付、虚拟支付、退款回调重复投递、退款与补偿交错、服务重启后的图片恢复。
  • 本轮没有修改线上数据、部署服务或提交 Git。