fix: 注册佣金计算任务 Handler 到队列处理器
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m19s

佣金计算任务 (commission:calculate) 的 Handler 已实现但未在队列处理器中注册,
导致支付成功后入队的佣金计算任务永远不会被消费执行。

变更内容:
- 在 pkg/queue/handler.go 中添加 registerCommissionCalculationHandler() 方法
- 创建所有需要的 Store 和 Service 依赖
- 在 RegisterHandlers() 中调用注册方法

修复后,订单支付成功将正确触发佣金计算和发放。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 16:08:03 +08:00
parent 8ab5ebc3af
commit b11edde720
6 changed files with 162 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-04

View File

@@ -0,0 +1,51 @@
## Context
支付成功后,订单服务通过 `enqueueCommissionCalculation()` 将佣金计算任务入队到 Asynq 队列(任务类型 `commission:calculate`)。然而,`pkg/queue/handler.go` 中的 `RegisterHandlers()` 方法没有注册对应的 Handler导致任务永远不会被消费。
**现有组件**
- `internal/task/commission_calculation.go` - 定义了 `CommissionCalculationHandler``NewCommissionCalculationHandler()`
- `internal/service/commission_calculation/service.go` - 实现了 `CalculateCommission()` 业务逻辑
- `pkg/constants/constants.go` - 定义了 `TaskTypeCommission = "commission:calculate"`
**缺失的连接**
- `pkg/queue/handler.go` 中没有调用 `task.NewCommissionCalculationHandler()` 并注册到 `mux`
## Goals / Non-Goals
**Goals:**
-`pkg/queue/handler.go` 中注册 `CommissionCalculationHandler`
- 确保所有依赖正确注入(`commission_calculation.Service` 及其依赖)
- 修复后队列中积压的 `commission:calculate` 任务能被正常消费
**Non-Goals:**
- 不修改佣金计算的业务逻辑
- 不修改任务入队的逻辑
- 不补偿历史丢失的任务(如果已从队列过期)
## Decisions
### 决策 1在 Handler 结构体中注入 `commission_calculation.Service`
**选项 A选中**:在 `pkg/queue/handler.go``registerCommissionCalculationHandler()` 方法中本地创建 Service 及其依赖
**选项 B**:修改 `NewHandler()` 签名,增加 `commission_calculation.Service` 参数
**选择理由**:选项 A 与现有的 `registerCommissionStatsHandlers()` 模式一致,不需要修改外部调用 `NewHandler()` 的代码。
### 决策 2依赖创建方式
`commission_calculation.Service` 需要以下依赖:
- `*gorm.DB` - Handler 已有
- 多个 StoreCommissionRecord、Shop、ShopPackageAllocation 等)- 需在方法内创建
- `*commission_stats.Service` - 需在方法内创建
- `*zap.Logger` - Handler 已有
参考 `registerCommissionStatsHandlers()` 的模式,在注册方法内部创建所有需要的 Store 和 Service。
## Risks / Trade-offs
| 风险 | 缓解措施 |
|------|---------|
| Store 实例重复创建 | 可接受Store 是无状态的轻量级对象,且只在启动时创建一次 |
| 历史任务可能已过期 | 提供补偿机制(后台扫描 `commission_status=pending` 的已支付订单) |
| 并发任务可能重复处理 | 已有幂等检查(`commission_status == calculated` 则跳过) |

View File

@@ -0,0 +1,33 @@
## Why
佣金计算任务 (`commission:calculate`) 的 Handler 没有在队列处理器中注册,导致支付成功后入队的佣金计算任务永远不会被消费执行。这是一个严重的生产问题:订单支付成功后,代理商的佣金无法自动计算和发放。
## What Changes
- **注册佣金计算任务 Handler**: 在 `pkg/queue/handler.go` 中添加 `CommissionCalculationHandler` 的注册
- **依赖注入**: 确保 `commission_calculation.Service` 的所有依赖正确注入到 Handler
## Capabilities
### New Capabilities
无新增功能,这是一个 bug 修复。
### Modified Capabilities
无规格变更,实现代码已存在但未正确连接。
## Impact
**受影响的代码**
- `pkg/queue/handler.go`: 添加 `registerCommissionCalculationHandler()` 方法
- 可能需要调整 `NewHandler()` 的依赖参数以支持创建 `commission_calculation.Service`
**受影响的业务**
- 修复后,所有支付成功的订单将正确触发佣金计算
- 历史未处理的 `commission:calculate` 任务将被消费(如果还在队列中)
**依赖**
- `internal/task/commission_calculation.go` - 已存在
- `internal/service/commission_calculation/service.go` - 已存在
- `pkg/constants/constants.go` - `TaskTypeCommission` 常量已存在

View File

@@ -0,0 +1,9 @@
## Implementation Fix
本变更不引入新需求,也不修改现有需求。
这是一个实现层面的 bug 修复:`commission:calculate` 任务的 Handler 已实现但未在队列处理器中注册。
修复后,现有的 `commission-trigger` spec 中定义的行为将正常工作:
- 支付成功后自动入队佣金计算任务 ✅(已实现)
- 佣金计算任务被消费执行 ❌(缺失注册)← 本次修复

View File

@@ -0,0 +1,19 @@
## 1. 注册佣金计算任务 Handler
- [x] 1.1 在 `pkg/queue/handler.go` 中添加 `registerCommissionCalculationHandler()` 方法
- 创建所有需要的 Store 实例
- 创建 `commission_stats.Service`
- 创建 `commission_calculation.Service`
- 创建 `task.NewCommissionCalculationHandler`
- 注册到 `h.mux.HandleFunc(constants.TaskTypeCommission, ...)`
- 添加日志记录
- [x] 1.2 在 `RegisterHandlers()` 中调用 `h.registerCommissionCalculationHandler()`
## 2. 验证
- [x] 2.1 编译验证:确保代码无编译错误
- 执行 `go build ./...`
- [x] 2.2 启动验证:确保 Worker 正常启动并注册了 Handler
- 检查启动日志中包含 "注册佣金计算任务处理器"

View File

@@ -6,6 +6,8 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/break/junhong_cmp_fiber/internal/service/commission_calculation"
"github.com/break/junhong_cmp_fiber/internal/service/commission_stats"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/internal/task"
"github.com/break/junhong_cmp_fiber/pkg/constants"
@@ -47,6 +49,7 @@ func (h *Handler) RegisterHandlers() *asynq.ServeMux {
h.registerIotCardImportHandler()
h.registerDeviceImportHandler()
h.registerCommissionStatsHandlers()
h.registerCommissionCalculationHandler()
h.logger.Info("所有任务处理器注册完成")
return h.mux
@@ -90,6 +93,51 @@ func (h *Handler) registerCommissionStatsHandlers() {
h.logger.Info("注册佣金统计归档任务处理器", zap.String("task_type", constants.TaskTypeCommissionStatsArchive))
}
func (h *Handler) registerCommissionCalculationHandler() {
// 创建所有需要的 Store 实例
commissionRecordStore := postgres.NewCommissionRecordStore(h.db, h.redis)
shopStore := postgres.NewShopStore(h.db, h.redis)
shopPackageAllocationStore := postgres.NewShopPackageAllocationStore(h.db)
shopSeriesAllocationStore := postgres.NewShopSeriesAllocationStore(h.db)
packageSeriesStore := postgres.NewPackageSeriesStore(h.db)
iotCardStore := postgres.NewIotCardStore(h.db, h.redis)
deviceStore := postgres.NewDeviceStore(h.db, h.redis)
walletStore := postgres.NewWalletStore(h.db, h.redis)
walletTransactionStore := postgres.NewWalletTransactionStore(h.db, h.redis)
orderStore := postgres.NewOrderStore(h.db, h.redis)
orderItemStore := postgres.NewOrderItemStore(h.db, h.redis)
packageStore := postgres.NewPackageStore(h.db)
commissionStatsStore := postgres.NewShopSeriesCommissionStatsStore(h.db)
// 创建 commission_stats.Service
commissionStatsService := commission_stats.New(commissionStatsStore)
// 创建 commission_calculation.Service
commissionCalculationService := commission_calculation.New(
h.db,
commissionRecordStore,
shopStore,
shopPackageAllocationStore,
shopSeriesAllocationStore,
packageSeriesStore,
iotCardStore,
deviceStore,
walletStore,
walletTransactionStore,
orderStore,
orderItemStore,
packageStore,
commissionStatsStore,
commissionStatsService,
h.logger,
)
// 创建并注册 Handler
commissionCalculationHandler := task.NewCommissionCalculationHandler(h.db, commissionCalculationService, h.logger)
h.mux.HandleFunc(constants.TaskTypeCommission, commissionCalculationHandler.HandleCommissionCalculation)
h.logger.Info("注册佣金计算任务处理器", zap.String("task_type", constants.TaskTypeCommission))
}
// GetMux 获取 ServeMux用于启动 Worker 服务器)
func (h *Handler) GetMux() *asynq.ServeMux {
return h.mux