## Why 当前系统中待支付订单创建后不会自动失效,导致大量"僵尸订单"占用数据库空间,且用户体验不佳(无法明确订单是否有效)。虽然现有规格文档(`iot-order`、`order-payment`)中提到了订单超时取消机制,但实际代码中完全未实现:缺少超时时间字段、定时任务、钱包解冻逻辑等。这是一个关键缺失功能,影响系统可用性和数据质量。 ## What Changes ### 订单超时自动失效(主要功能) - 新增订单超时自动失效机制,待支付订单 30 分钟后自动取消 - 新增数据库字段:`tb_order.expires_at`(订单过期时间) - 新增 Asynq 定时任务:每分钟扫描并取消超时订单 - 新增常量定义:`OrderExpireTimeout`、`TaskTypeOrderExpire` - 完善订单取消逻辑:支持钱包余额自动解冻(混合支付场景) - 新增订单列表查询条件:过期状态筛选 - 完善订单创建流程:自动设置 `expires_at = created_at + 30分钟` ### 架构优化:重构现有定时任务为 Asynq Scheduler - 将现有的 `time.Ticker`/`time.Timer` 定时任务迁移到 Asynq Scheduler - 重构告警检查器(`startAlertChecker`)为 Asynq 周期任务(`@every 1m`) - 重构数据清理定时任务(`startCleanupScheduler`)为 Asynq 周期任务(每天凌晨2点) - 新增常量定义:`TaskTypeAlertCheck`、`TaskTypeDataCleanup` - 移除 `cmd/worker/main.go` 中的原生定时任务实现(`startAlertChecker`、`startCleanupScheduler`) - 统一所有定时任务调度机制为 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.go`、`alert_check.go`、`data_cleanup.go` 定时任务 Handler - `pkg/constants/constants.go`:新增超时和任务类型相关常量(`TaskTypeOrderExpire`、`TaskTypeAlertCheck`、`TaskTypeDataCleanup`) - `internal/store/postgres/order_store.go`:新增批量查询超时订单方法 - `cmd/worker/main.go`: - 创建和启动 Asynq Scheduler 实例 - 注册 3 个周期任务(订单超时、告警检查、数据清理) - 移除原生定时任务实现(`startAlertChecker`、`startCleanupScheduler`) - `pkg/queue/handler.go`:注册 3 个定时任务 Handler **API 影响**: - 订单列表 API(`GET /api/admin/orders`、`GET /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`(需手动处理或忽略)