docs(01-02): 完成 PollingHandler 注入 asynq.Client 修复断链计划摘要
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
- [x] **CRITICAL-01**: 实名状态常量统一 — `parseRealnameStatus` 写入值 2 改为常量 1,Model 注释统一,全链路使用 `constants.RealNameStatusVerified`
|
- [x] **CRITICAL-01**: 实名状态常量统一 — `parseRealnameStatus` 写入值 2 改为常量 1,Model 注释统一,全链路使用 `constants.RealNameStatusVerified`
|
||||||
- [x] **CRITICAL-02**: C 端实名校验修复 — `client_order/service.go` 实名判断改用 `constants.RealNameStatusVerified`(依赖 CRITICAL-01)
|
- [x] **CRITICAL-02**: C 端实名校验修复 — `client_order/service.go` 实名判断改用 `constants.RealNameStatusVerified`(依赖 CRITICAL-01)
|
||||||
- [ ] **CRITICAL-03**: 实名激活任务断链修复 — `PollingHandler` 注入 `asynq.Client`,删除 RPush 降级方案,改用 `asynq.Client.EnqueueContext()`
|
- [x] **CRITICAL-03**: 实名激活任务断链修复 — `PollingHandler` 注入 `asynq.Client`,删除 RPush 降级方案,改用 `asynq.Client.EnqueueContext()`
|
||||||
- [ ] **CRITICAL-04**: 充值回调后自动购包触发 — `recharge/service.go` 在 HandlePaymentCallback 成功后入队 `TaskTypeAutoPurchaseAfterRecharge`;注册 `AutoPurchaseHandler`
|
- [ ] **CRITICAL-04**: 充值回调后自动购包触发 — `recharge/service.go` 在 HandlePaymentCallback 成功后入队 `TaskTypeAutoPurchaseAfterRecharge`;注册 `AutoPurchaseHandler`
|
||||||
- [ ] **CRITICAL-05**: 自动购包佣金链补全 — `AutoPurchaseHandler.ProcessTask()` 事务提交成功后入队 `TaskTypeCommission`
|
- [ ] **CRITICAL-05**: 自动购包佣金链补全 — `AutoPurchaseHandler.ProcessTask()` 事务提交成功后入队 `TaskTypeCommission`
|
||||||
- [x] **CRITICAL-06**: 代购订单金额修正 — 场景 5(代理代购下级)`sellerCostPrice` 全部 6 处逐一审查,确保使用 `operatorCostPrice`(非 `buyerCostPrice`)
|
- [x] **CRITICAL-06**: 代购订单金额修正 — 场景 5(代理代购下级)`sellerCostPrice` 全部 6 处逐一审查,确保使用 `operatorCostPrice`(非 `buyerCostPrice`)
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
|--------|-------|--------|
|
|--------|-------|--------|
|
||||||
| CRITICAL-01 | Phase 1 | Complete |
|
| CRITICAL-01 | Phase 1 | Complete |
|
||||||
| CRITICAL-02 | Phase 1 | Complete |
|
| CRITICAL-02 | Phase 1 | Complete |
|
||||||
| CRITICAL-03 | Phase 1 | Pending |
|
| CRITICAL-03 | Phase 1 | Complete |
|
||||||
| CRITICAL-04 | Phase 1 | Pending |
|
| CRITICAL-04 | Phase 1 | Pending |
|
||||||
| CRITICAL-05 | Phase 1 | Pending |
|
| CRITICAL-05 | Phase 1 | Pending |
|
||||||
| CRITICAL-06 | Phase 1 | Complete |
|
| CRITICAL-06 | Phase 1 | Complete |
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
- [x] 01-01-PLAN.md — CRITICAL-01/02:实名状态常量统一 + C 端实名校验修复(Wave 1)
|
- [x] 01-01-PLAN.md — CRITICAL-01/02:实名状态常量统一 + C 端实名校验修复(Wave 1)
|
||||||
- [ ] 01-02-PLAN.md — CRITICAL-03:实名激活任务断链(PollingHandler 注入 asynqClient)(Wave 2)
|
- [x] 01-02-PLAN.md — CRITICAL-03:实名激活任务断链(PollingHandler 注入 asynqClient)(Wave 2)
|
||||||
- [ ] 01-03-PLAN.md — CRITICAL-04/05:充值回调触发自动购包 + 佣金链补全(Wave 2,parallel)
|
- [ ] 01-03-PLAN.md — CRITICAL-04/05:充值回调触发自动购包 + 佣金链补全(Wave 2,parallel)
|
||||||
- [x] 01-04-PLAN.md — CRITICAL-06:代购订单 sellerCostPrice 6 处语义审查修正(Wave 1,parallel)
|
- [x] 01-04-PLAN.md — CRITICAL-06:代购订单 sellerCostPrice 6 处语义审查修正(Wave 1,parallel)
|
||||||
- [x] 01-05-PLAN.md — CRITICAL-07/08:设备导入 IMEI + 提现冻结并发校验(Wave 1,parallel)
|
- [x] 01-05-PLAN.md — CRITICAL-07/08:设备导入 IMEI + 提现冻结并发校验(Wave 1,parallel)
|
||||||
@@ -118,7 +118,7 @@ Plans:
|
|||||||
|
|
||||||
| Phase | Plans Complete | Status | Completed |
|
| Phase | Plans Complete | Status | Completed |
|
||||||
|-------|----------------|--------|-----------|
|
|-------|----------------|--------|-----------|
|
||||||
| 1. P0 紧急修复 | 2/5 | In Progress| |
|
| 1. P0 紧急修复 | 4/5 | In Progress| |
|
||||||
| 2. 权限/财务/实名/轮询修复 | 0/1 | Not started | - |
|
| 2. 权限/财务/实名/轮询修复 | 0/1 | Not started | - |
|
||||||
| 3. 设备体系完善 | 0/1 | Not started | - |
|
| 3. 设备体系完善 | 0/1 | Not started | - |
|
||||||
| 4. 退款 + 支付 + 运营修复 | 0/1 | Not started | - |
|
| 4. 退款 + 支付 + 运营修复 | 0/1 | Not started | - |
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: unknown
|
status: unknown
|
||||||
last_updated: "2026-03-27T15:25:28.566Z"
|
last_updated: "2026-03-27T15:30:07.725Z"
|
||||||
progress:
|
progress:
|
||||||
total_phases: 6
|
total_phases: 6
|
||||||
completed_phases: 0
|
completed_phases: 0
|
||||||
total_plans: 5
|
total_plans: 5
|
||||||
completed_plans: 3
|
completed_plans: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
# Project State — 君鸿卡管系统
|
# Project State — 君鸿卡管系统
|
||||||
@@ -22,7 +22,7 @@ progress:
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 01 (p0) — EXECUTING
|
Phase: 01 (p0) — EXECUTING
|
||||||
Plan: 2 of 5
|
Plan: 3 of 5
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
|-------|-------|
|
|-------|-------|
|
||||||
| **Current Phase** | 1 — P0 紧急修复 |
|
| **Current Phase** | 1 — P0 紧急修复 |
|
||||||
@@ -74,6 +74,7 @@ Progress: [ 1 ]──[ 2 ]──[ 3 ]──[ 4 ]──[ 5 ]──[ 6 ]
|
|||||||
| Phase 01-p0 P05 | 8 | 2 tasks | 3 files |
|
| Phase 01-p0 P05 | 8 | 2 tasks | 3 files |
|
||||||
| Phase 01-p0 P01 | 15 | 2 tasks | 7 files |
|
| Phase 01-p0 P01 | 15 | 2 tasks | 7 files |
|
||||||
| Phase 01-p0 P04 | 4min | 1 tasks | 1 files |
|
| Phase 01-p0 P04 | 4min | 1 tasks | 1 files |
|
||||||
|
| Phase 01-p0 P02 | 3min | 1 tasks | 2 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
|
|||||||
131
.planning/phases/01-p0/01-02-SUMMARY.md
Normal file
131
.planning/phases/01-p0/01-02-SUMMARY.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
---
|
||||||
|
phase: 01-p0
|
||||||
|
plan: 02
|
||||||
|
subsystem: task/polling
|
||||||
|
tags: [bug-fix, asynq, realname-activation, critical]
|
||||||
|
one_liner: "修复 PollingHandler 缺失 asynq.Client 导致实名激活任务进入 RPush 降级而非 Asynq 队列的断链问题"
|
||||||
|
dependency_graph:
|
||||||
|
requires:
|
||||||
|
- 01-01 (CRITICAL-02 实名状态常量统一)
|
||||||
|
provides:
|
||||||
|
- CRITICAL-03: PollingHandler 正确通过 Asynq 入队实名激活任务
|
||||||
|
affects:
|
||||||
|
- internal/task/polling_handler.go
|
||||||
|
- pkg/queue/handler.go
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "依赖注入:通过构造函数参数传入 asynq.Client"
|
||||||
|
- "asynq.Client.EnqueueContext 正式入队"
|
||||||
|
key_files:
|
||||||
|
modified:
|
||||||
|
- internal/task/polling_handler.go
|
||||||
|
- pkg/queue/handler.go
|
||||||
|
decisions:
|
||||||
|
- "删除 RPush 降级方案及 _ = task 废弃代码,直接使用 EnqueueContext 入队"
|
||||||
|
- "asynqClient 参数位置:redis 之后、gatewayClient 之前,与其他 Handler 构造函数风格一致"
|
||||||
|
metrics:
|
||||||
|
duration: "3min"
|
||||||
|
completed: "2026-03-27"
|
||||||
|
tasks: 1
|
||||||
|
files: 2
|
||||||
|
requirements:
|
||||||
|
- CRITICAL-03
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 01 Plan 02: PollingHandler 注入 asynq.Client 修复实名激活断链 Summary
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
修复 CRITICAL-03:`triggerFirstRealnameActivation` 因缺少 `asynq.Client` 注入,降级使用 Redis RPush 将任务写入无消费者的列表,导致首次实名后套餐激活任务永远不被消费。
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
### 修改文件
|
||||||
|
|
||||||
|
**`internal/task/polling_handler.go`**
|
||||||
|
|
||||||
|
1. `PollingHandler` struct 新增 `asynqClient *asynq.Client` 字段
|
||||||
|
2. `NewPollingHandler` 构造函数新增 `asynqClient *asynq.Client` 参数(位置:redis 之后,gatewayClient 之前)
|
||||||
|
3. `triggerFirstRealnameActivation` 改为 `h.asynqClient.EnqueueContext(ctx, task)`,删除 RPush 降级代码和 `_ = task`
|
||||||
|
|
||||||
|
**`pkg/queue/handler.go`**
|
||||||
|
|
||||||
|
`registerPollingHandlers` 调用 `task.NewPollingHandler` 时补充 `h.asynqClient` 参数(Handler struct 已有此字段,直接传入)
|
||||||
|
|
||||||
|
### 关键代码对比
|
||||||
|
|
||||||
|
**修改前(降级代码):**
|
||||||
|
|
||||||
|
```go
|
||||||
|
// polling_handler.go
|
||||||
|
type PollingHandler struct {
|
||||||
|
db *gorm.DB
|
||||||
|
redis *redis.Client
|
||||||
|
// asynqClient 缺失
|
||||||
|
gatewayClient *gateway.Client
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// triggerFirstRealnameActivation 内
|
||||||
|
task := asynq.NewTask(...)
|
||||||
|
activationKey := constants.RedisPollingManualQueueKey(constants.TaskTypePackageFirstActivation)
|
||||||
|
h.redis.RPush(ctx, activationKey, string(payloadBytes)) // 写入无消费者的列表
|
||||||
|
_ = task // task 被丢弃
|
||||||
|
```
|
||||||
|
|
||||||
|
**修改后(正确入队):**
|
||||||
|
|
||||||
|
```go
|
||||||
|
// polling_handler.go
|
||||||
|
type PollingHandler struct {
|
||||||
|
db *gorm.DB
|
||||||
|
redis *redis.Client
|
||||||
|
asynqClient *asynq.Client // 新增,用于提交 Asynq 任务
|
||||||
|
gatewayClient *gateway.Client
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// triggerFirstRealnameActivation 内
|
||||||
|
task := asynq.NewTask(...)
|
||||||
|
if _, err := h.asynqClient.EnqueueContext(ctx, task); err != nil {
|
||||||
|
h.logger.Warn("提交首次实名激活任务失败", ...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification Results
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ go build ./... — 编译通过
|
||||||
|
✅ rg "_ = task" internal/task/polling_handler.go → PASS: _ = task 已删除
|
||||||
|
✅ rg "asynqClient.EnqueueContext" internal/task/polling_handler.go → PASS: EnqueueContext 已存在
|
||||||
|
✅ registerPollingHandlers 传入 h.asynqClient 参数
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commits
|
||||||
|
|
||||||
|
| Task | Commit | Files |
|
||||||
|
|------|--------|-------|
|
||||||
|
| Task 1: PollingHandler 注入 asynqClient(CRITICAL-03)| `20b4b6d` | internal/task/polling_handler.go, pkg/queue/handler.go |
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None - 计划执行完全按规格书执行,无偏差。
|
||||||
|
|
||||||
|
## CRITICAL-03 完成状态
|
||||||
|
|
||||||
|
✅ **CRITICAL-03 已修复**
|
||||||
|
|
||||||
|
- PollingHandler struct 含 asynqClient 字段 ✅
|
||||||
|
- NewPollingHandler 接受 asynqClient 参数 ✅
|
||||||
|
- triggerFirstRealnameActivation 使用 EnqueueContext,不再 RPush ✅
|
||||||
|
- `_ = task` 已删除 ✅
|
||||||
|
- pkg/queue/handler.go 传入 h.asynqClient ✅
|
||||||
|
- go build ./... 编译通过 ✅
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- `internal/task/polling_handler.go` — FOUND ✅
|
||||||
|
- `pkg/queue/handler.go` — FOUND ✅
|
||||||
|
- Commit `20b4b6d` — FOUND ✅
|
||||||
Reference in New Issue
Block a user