Files
junhong_cmp_fiber/openspec/changes/implement-order-expiration/proposal.md
huang 5bb0ff0ddf
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m54s
fix: 修复代理钱包订单创建逻辑,拆分后台/H5端下单方法并归档变更
- 拆分订单创建为 CreateAdminOrder(后台一步支付)和 CreateH5Order(H5 两步支付)
- 新增 CreateAdminOrderRequest DTO,后台仅允许 wallet/offline 支付方式
- 同步 delta specs 到主规格(order-payment 更新 + admin-order-creation 新增)
- 归档 fix-agent-wallet-order-creation 变更
- 新增 implement-order-expiration 变更提案
2026-02-28 16:31:31 +08:00

75 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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`(需手动处理或忽略)