From b11edde72072b93e5f013d887450f787df9c6586 Mon Sep 17 00:00:00 2001 From: huang Date: Wed, 4 Feb 2026 16:08:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B3=A8=E5=86=8C=E4=BD=A3=E9=87=91?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E4=BB=BB=E5=8A=A1=20Handler=20=E5=88=B0?= =?UTF-8?q?=E9=98=9F=E5=88=97=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 佣金计算任务 (commission:calculate) 的 Handler 已实现但未在队列处理器中注册, 导致支付成功后入队的佣金计算任务永远不会被消费执行。 变更内容: - 在 pkg/queue/handler.go 中添加 registerCommissionCalculationHandler() 方法 - 创建所有需要的 Store 和 Service 依赖 - 在 RegisterHandlers() 中调用注册方法 修复后,订单支付成功将正确触发佣金计算和发放。 Co-Authored-By: Claude Opus 4.5 --- .../.openspec.yaml | 2 + .../design.md | 51 +++++++++++++++++++ .../proposal.md | 33 ++++++++++++ .../specs/commission-trigger/spec.md | 9 ++++ .../tasks.md | 19 +++++++ pkg/queue/handler.go | 48 +++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/.openspec.yaml create mode 100644 openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/design.md create mode 100644 openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/proposal.md create mode 100644 openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/specs/commission-trigger/spec.md create mode 100644 openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/tasks.md diff --git a/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/.openspec.yaml b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/.openspec.yaml new file mode 100644 index 0000000..4269af7 --- /dev/null +++ b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-02-04 diff --git a/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/design.md b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/design.md new file mode 100644 index 0000000..7ce1dc6 --- /dev/null +++ b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/design.md @@ -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 已有 +- 多个 Store(CommissionRecord、Shop、ShopPackageAllocation 等)- 需在方法内创建 +- `*commission_stats.Service` - 需在方法内创建 +- `*zap.Logger` - Handler 已有 + +参考 `registerCommissionStatsHandlers()` 的模式,在注册方法内部创建所有需要的 Store 和 Service。 + +## Risks / Trade-offs + +| 风险 | 缓解措施 | +|------|---------| +| Store 实例重复创建 | 可接受,Store 是无状态的轻量级对象,且只在启动时创建一次 | +| 历史任务可能已过期 | 提供补偿机制(后台扫描 `commission_status=pending` 的已支付订单) | +| 并发任务可能重复处理 | 已有幂等检查(`commission_status == calculated` 则跳过) | diff --git a/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/proposal.md b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/proposal.md new file mode 100644 index 0000000..cbce2f1 --- /dev/null +++ b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/proposal.md @@ -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` 常量已存在 diff --git a/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/specs/commission-trigger/spec.md b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/specs/commission-trigger/spec.md new file mode 100644 index 0000000..8566e09 --- /dev/null +++ b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/specs/commission-trigger/spec.md @@ -0,0 +1,9 @@ +## Implementation Fix + +本变更不引入新需求,也不修改现有需求。 + +这是一个实现层面的 bug 修复:`commission:calculate` 任务的 Handler 已实现但未在队列处理器中注册。 + +修复后,现有的 `commission-trigger` spec 中定义的行为将正常工作: +- 支付成功后自动入队佣金计算任务 ✅(已实现) +- 佣金计算任务被消费执行 ❌(缺失注册)← 本次修复 diff --git a/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/tasks.md b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/tasks.md new file mode 100644 index 0000000..4aab38a --- /dev/null +++ b/openspec/changes/archive/2026-02-04-fix-commission-calculation-handler-registration/tasks.md @@ -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 + - 检查启动日志中包含 "注册佣金计算任务处理器" diff --git a/pkg/queue/handler.go b/pkg/queue/handler.go index e732721..696ddeb 100644 --- a/pkg/queue/handler.go +++ b/pkg/queue/handler.go @@ -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