修复并发,暂时的,不够完整,后续还是需要重新设计,这个太乱了,傻逼AI
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m22s

This commit is contained in:
2026-05-11 17:19:40 +08:00
parent 05a5694a5f
commit b7369a9c71
16 changed files with 270 additions and 68 deletions

View File

@@ -70,7 +70,7 @@ type DatabaseConfig struct {
// QueueConfig 任务队列配置
type QueueConfig struct {
Concurrency int `mapstructure:"concurrency"` // Worker 并发数默认10
Queues map[string]int `mapstructure:"queues"` // 队列优先级配置(队列名 -> 权重
Queues map[string]int `mapstructure:"queues"` // Asynq 队列取任务权重(不是业务并发上限
RetryMax int `mapstructure:"retry_max"` // 最大重试次数默认5
Timeout time.Duration `mapstructure:"timeout"` // 任务超时时间默认10m
}

View File

@@ -172,14 +172,125 @@ const (
// 队列配置常量
const (
QueueCritical = "critical" // 关键任务队列
QueueDefault = "default" // 默认队列
QueueLow = "low" // 低优先级队列
DefaultRetryMax = 5
DefaultTimeout = 10 * time.Minute
DefaultConcurrency = 10
QueueCritical = "critical" // 旧版关键任务队列(兼容历史任务)
QueueDefault = "default" // 旧版默认队列(兼容历史任务)
QueueLow = "low" // 旧版低优先级队列(兼容历史任务)
QueueEmailSend = TaskTypeEmailSend // 发送邮件任务队列
QueueCommission = TaskTypeCommission // 分佣计算任务队列
QueueIotCardImport = TaskTypeIotCardImport // IoT 卡导入任务队列
QueueDeviceImport = TaskTypeDeviceImport // 设备导入任务队列
QueueExportDispatch = TaskTypeExportDispatch // 导出分发任务队列
QueueExportShard = TaskTypeExportShard // 导出分片任务队列
QueueExportFinalize = TaskTypeExportFinalize // 导出收尾任务队列
QueueCommissionStatsUpdate = TaskTypeCommissionStatsUpdate // 佣金统计更新任务队列
QueueCommissionStatsSync = TaskTypeCommissionStatsSync // 佣金统计同步任务队列
QueueCommissionStatsArchive = TaskTypeCommissionStatsArchive // 佣金统计归档任务队列
QueuePollingRealname = TaskTypePollingRealname // 实名轮询任务队列
QueuePollingCarddata = TaskTypePollingCarddata // 流量轮询任务队列
QueuePollingPackage = TaskTypePollingPackage // 套餐轮询任务队列
QueuePollingProtect = TaskTypePollingProtect // 保护期轮询任务队列
QueuePollingCardStatus = TaskTypePollingCardStatus // 卡状态轮询任务队列
QueuePackageFirstActivation = TaskTypePackageFirstActivation // 首次实名激活任务队列
QueuePackageQueueActivation = TaskTypePackageQueueActivation // 主套餐排队激活任务队列
QueuePackageDataReset = TaskTypePackageDataReset // 套餐流量重置任务队列
QueueOrderExpire = TaskTypeOrderExpire // 订单超时取消任务队列
QueueAutoPurchase = TaskTypeAutoPurchaseAfterRecharge // 充值后自动购包任务队列
QueueAlertCheck = TaskTypeAlertCheck // 告警检查任务队列
QueueDataCleanup = TaskTypeDataCleanup // 数据清理任务队列
QueueDailyTrafficFlush = TaskTypeDailyTrafficFlush // 每日流量落盘任务队列
DefaultRetryMax = 5 // 默认任务最大重试次数
DefaultTimeout = 10 * time.Minute // 默认任务超时时间
DefaultConcurrency = 10 // 默认 Worker 并发数
)
// QueueForTaskType 根据任务类型返回独立队列名。
func QueueForTaskType(taskType string) string {
switch taskType {
case TaskTypeEmailSend:
return QueueEmailSend
case TaskTypeCommission:
return QueueCommission
case TaskTypeIotCardImport:
return QueueIotCardImport
case TaskTypeDeviceImport:
return QueueDeviceImport
case TaskTypeExportDispatch:
return QueueExportDispatch
case TaskTypeExportShard:
return QueueExportShard
case TaskTypeExportFinalize:
return QueueExportFinalize
case TaskTypeCommissionStatsUpdate:
return QueueCommissionStatsUpdate
case TaskTypeCommissionStatsSync:
return QueueCommissionStatsSync
case TaskTypeCommissionStatsArchive:
return QueueCommissionStatsArchive
case TaskTypePollingRealname:
return QueuePollingRealname
case TaskTypePollingCarddata:
return QueuePollingCarddata
case TaskTypePollingPackage:
return QueuePollingPackage
case TaskTypePollingProtect:
return QueuePollingProtect
case TaskTypePollingCardStatus:
return QueuePollingCardStatus
case TaskTypePackageFirstActivation:
return QueuePackageFirstActivation
case TaskTypePackageQueueActivation:
return QueuePackageQueueActivation
case TaskTypePackageDataReset:
return QueuePackageDataReset
case TaskTypeOrderExpire:
return QueueOrderExpire
case TaskTypeAutoPurchaseAfterRecharge:
return QueueAutoPurchase
case TaskTypeAlertCheck:
return QueueAlertCheck
case TaskTypeDataCleanup:
return QueueDataCleanup
case TaskTypeDailyTrafficFlush:
return QueueDailyTrafficFlush
default:
return QueueDefault
}
}
// DefaultTaskQueueWeights 返回 Worker 默认监听的全部任务队列及其权重。
func DefaultTaskQueueWeights() map[string]int {
return map[string]int{
QueueCritical: 6,
QueueIotCardImport: 6,
QueueDeviceImport: 6,
QueueAutoPurchase: 5,
QueuePackageFirstActivation: 5,
QueuePackageQueueActivation: 5,
QueueOrderExpire: 4,
QueueEmailSend: 4,
QueueExportDispatch: 4,
QueueExportFinalize: 4,
QueueCommission: 3,
QueueAlertCheck: 3,
QueueExportShard: 2,
QueueCommissionStatsUpdate: 2,
QueueCommissionStatsSync: 2,
QueueCommissionStatsArchive: 2,
QueuePollingRealname: 1,
QueuePollingCarddata: 1,
QueuePollingPackage: 1,
QueuePollingProtect: 1,
QueuePollingCardStatus: 1,
QueuePackageDataReset: 1,
QueueDataCleanup: 1,
QueueDailyTrafficFlush: 1,
QueueDefault: 1,
QueueLow: 1,
}
}
// 导出任务相关常量
const (
ExportTaskSceneDevice = "device" // 导出场景:设备

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/break/junhong_cmp_fiber/pkg/config"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/bytedance/sonic"
"github.com/hibiken/asynq"
"github.com/redis/go-redis/v9"
@@ -38,6 +39,12 @@ func NewClient(redisClient *redis.Client, logger *zap.Logger) *Client {
// payload 必须传入 struct 或 map禁止传入 []byte。
// 传入 []byte 会导致 sonic.Marshal 将其 base64 编码handler 解析时类型不匹配。
func (c *Client) EnqueueTask(ctx context.Context, taskType string, payload interface{}, opts ...asynq.Option) error {
if _, ok := payload.([]byte); ok {
c.logger.Error("任务载荷类型错误,禁止传入 []byte",
zap.String("task_type", taskType))
return fmt.Errorf("task payload must be struct or map, got []byte")
}
// 内部统一序列化,调用方无需预先 Marshal
payloadBytes, err := sonic.Marshal(payload)
if err != nil {
@@ -47,6 +54,8 @@ func (c *Client) EnqueueTask(ctx context.Context, taskType string, payload inter
return fmt.Errorf("failed to marshal task payload: %w", err)
}
opts = append(opts, asynq.Queue(constants.QueueForTaskType(taskType)))
// 创建任务
task := asynq.NewTask(taskType, payloadBytes, opts...)
@@ -78,13 +87,12 @@ func (c *Client) Close() error {
// ParseQueueConfig 解析队列配置为 Asynq 格式
func ParseQueueConfig(cfg *config.QueueConfig) map[string]int {
queues := constants.DefaultTaskQueueWeights()
if cfg.Queues != nil && len(cfg.Queues) > 0 {
return cfg.Queues
}
// 默认队列优先级
return map[string]int{
"critical": 6,
"default": 3,
"low": 1,
// 配置只覆盖权重;任务队列全集由代码兜底,避免漏监听新队列。
for queueName, weight := range cfg.Queues {
queues[queueName] = weight
}
}
return queues
}