Files
junhong_cmp_fiber/openspec/changes/archive/2025-07-27-implement-order-expiration/proposal.md
huang e661b59bb9
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
feat: 实现订单超时自动取消功能,支持钱包余额解冻和 Asynq Scheduler 统一调度
- 新增 expires_at 字段和复合索引,待支付订单 30 分钟超时自动取消
- 实现 cancelOrder/unfreezeWalletForCancel 钱包余额解冻逻辑
- 创建 Asynq 定时任务(order_expire/alert_check/data_cleanup)
- 将原有 time.Ticker 轮询迁移至 Asynq Scheduler 统一调度
- 同步 delta specs 到 main specs 并归档变更
2026-02-28 17:16:15 +08:00

3.7 KiB
Raw Blame History

Why

当前系统中待支付订单创建后不会自动失效,导致大量"僵尸订单"占用数据库空间,且用户体验不佳(无法明确订单是否有效)。虽然现有规格文档(iot-orderorder-payment)中提到了订单超时取消机制,但实际代码中完全未实现:缺少超时时间字段、定时任务、钱包解冻逻辑等。这是一个关键缺失功能,影响系统可用性和数据质量。

What Changes

订单超时自动失效(主要功能)

  • 新增订单超时自动失效机制,待支付订单 30 分钟后自动取消
  • 新增数据库字段:tb_order.expires_at(订单过期时间)
  • 新增 Asynq 定时任务:每分钟扫描并取消超时订单
  • 新增常量定义:OrderExpireTimeoutTaskTypeOrderExpire
  • 完善订单取消逻辑:支持钱包余额自动解冻(混合支付场景)
  • 新增订单列表查询条件:过期状态筛选
  • 完善订单创建流程:自动设置 expires_at = created_at + 30分钟

架构优化:重构现有定时任务为 Asynq Scheduler

  • 将现有的 time.Ticker/time.Timer 定时任务迁移到 Asynq Scheduler
  • 重构告警检查器(startAlertChecker)为 Asynq 周期任务(@every 1m
  • 重构数据清理定时任务(startCleanupScheduler)为 Asynq 周期任务每天凌晨2点
  • 新增常量定义:TaskTypeAlertCheckTaskTypeDataCleanup
  • 移除 cmd/worker/main.go 中的原生定时任务实现(startAlertCheckerstartCleanupScheduler
  • 统一所有定时任务调度机制为 Asynq Scheduler

Capabilities

New Capabilities

  • order-expiration:订单超时自动失效机制。包含:超时时间配置、定时扫描任务、自动取消逻辑、钱包余额解冻、过期状态查询。

Modified Capabilities

  • iot-order:补充订单超时失效的需求(原规格中提到但未详细定义)
  • order-payment:补充钱包支付订单取消时的余额解冻需求

Impact

数据模型

  • tb_order 表新增字段:expires_at TIMESTAMP
  • 新增索引:idx_order_expires(expires_at, payment_status)

代码影响

  • internal/model/order.go:新增 ExpiresAt 字段
  • internal/service/order/service.go
    • Create() 方法设置过期时间
    • Cancel() 方法支持钱包解冻
    • 新增 CancelExpiredOrders() 方法
  • internal/task/:新增 order_expire.goalert_check.godata_cleanup.go 定时任务 Handler
  • pkg/constants/constants.go:新增超时和任务类型相关常量(TaskTypeOrderExpireTaskTypeAlertCheckTaskTypeDataCleanup
  • internal/store/postgres/order_store.go:新增批量查询超时订单方法
  • cmd/worker/main.go
    • 创建和启动 Asynq Scheduler 实例
    • 注册 3 个周期任务(订单超时、告警检查、数据清理)
    • 移除原生定时任务实现(startAlertCheckerstartCleanupScheduler
  • pkg/queue/handler.go:注册 3 个定时任务 Handler

API 影响

  • 订单列表 APIGET /api/admin/ordersGET /api/h5/orders):新增过期状态筛选条件

依赖

  • Asynq 任务队列(已有)
  • Redis已有用于任务调度
  • 钱包服务(internal/service/wallet/,已有)

性能考虑

  • 定时任务每分钟执行一次,批量处理超时订单(单次最多 100 条)
  • 使用复合索引 idx_order_expires(expires_at, payment_status) 优化查询
  • 预估查询耗时 < 50ms单批次处理耗时 < 5s

数据库迁移

  • 需要执行迁移脚本:migrations/000xxx_add_order_expiration.up.sql
  • 需要回滚脚本:migrations/000xxx_add_order_expiration.down.sql
  • 对现有数据的影响:已存在的待支付订单 expires_at 初始化为 NULL(需手动处理或忽略)