修复并发,暂时的,不够完整,后续还是需要重新设计,这个太乱了,傻逼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

@@ -484,7 +484,7 @@ func (h *PackageActivationHandler) enqueueActivationTask(ctx context.Context, pa
task := asynq.NewTask(constants.TaskTypePackageQueueActivation, payloadBytes,
asynq.MaxRetry(3),
asynq.Timeout(30*time.Second),
asynq.Queue(constants.QueueDefault),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypePackageQueueActivation)),
)
_, err = h.queueClient.Enqueue(task)

View File

@@ -263,7 +263,7 @@ func (s *Scheduler) enqueueBatch(ctx context.Context, taskType string, cardIDs [
task := asynq.NewTask(taskType, payloadBytes,
asynq.MaxRetry(0),
asynq.Timeout(30*time.Second),
asynq.Queue(constants.QueueDefault),
asynq.Queue(constants.QueueForTaskType(taskType)),
)
if _, err := s.queueClient.Enqueue(task); err != nil {
s.logger.Error("提交任务失败,回退至分片队列防止卡永久丢失",

View File

@@ -13,6 +13,7 @@ import (
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/hibiken/asynq"
"gorm.io/gorm"
)
@@ -70,7 +71,12 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportDeviceReq
}
payload := DeviceImportPayload{TaskID: task.ID}
err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeDeviceImport, payload)
err := s.queueClient.EnqueueTask(
ctx,
constants.TaskTypeDeviceImport,
payload,
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeDeviceImport)),
)
if err != nil {
s.importTaskStore.UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败: "+err.Error())
appErr := errors.Wrap(errors.CodeInternalError, err, "任务入队失败")

View File

@@ -10,7 +10,6 @@ import (
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/bytedance/sonic"
"github.com/hibiken/asynq"
"go.uber.org/zap"
)
@@ -39,21 +38,12 @@ func (s *Service) SendWelcomeEmail(ctx context.Context, userID uint, email strin
Body: "感谢您注册我们的服务!我们很高兴为您提供服务。",
}
payloadBytes, err := sonic.Marshal(payload)
if err != nil {
s.logger.Error("序列化邮件任务载荷失败",
zap.Uint("user_id", userID),
zap.String("email", email),
zap.Error(err))
return errors.Wrap(errors.CodeInternalError, err, "序列化邮件任务载荷失败")
}
// 提交任务到队列
err = s.queueClient.EnqueueTask(
err := s.queueClient.EnqueueTask(
ctx,
constants.TaskTypeEmailSend,
payloadBytes,
asynq.Queue(constants.QueueDefault),
payload,
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeEmailSend)),
asynq.MaxRetry(constants.DefaultRetryMax),
)
@@ -82,20 +72,12 @@ func (s *Service) SendPasswordResetEmail(ctx context.Context, email string, rese
Body: fmt.Sprintf("您的密码重置令牌是: %s\n此令牌将在 1 小时后过期。", resetToken),
}
payloadBytes, err := sonic.Marshal(payload)
if err != nil {
s.logger.Error("序列化密码重置邮件任务载荷失败",
zap.String("email", email),
zap.Error(err))
return errors.Wrap(errors.CodeInternalError, err, "序列化密码重置邮件任务载荷失败")
}
// 提交任务到队列(高优先级)
err = s.queueClient.EnqueueTask(
// 提交任务到独立邮件队列
err := s.queueClient.EnqueueTask(
ctx,
constants.TaskTypeEmailSend,
payloadBytes,
asynq.Queue(constants.QueueCritical), // 密码重置使用高优先级队列
payload,
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeEmailSend)),
asynq.MaxRetry(constants.DefaultRetryMax),
)
@@ -122,20 +104,12 @@ func (s *Service) SendNotificationEmail(ctx context.Context, to string, subject
Body: body,
}
payloadBytes, err := sonic.Marshal(payload)
if err != nil {
s.logger.Error("序列化通知邮件任务载荷失败",
zap.String("to", to),
zap.Error(err))
return errors.Wrap(errors.CodeInternalError, err, "序列化通知邮件任务载荷失败")
}
// 提交任务到队列(低优先级)
err = s.queueClient.EnqueueTask(
// 提交任务到独立邮件队列
err := s.queueClient.EnqueueTask(
ctx,
constants.TaskTypeEmailSend,
payloadBytes,
asynq.Queue(constants.QueueLow), // 通知邮件使用低优先级队列
payload,
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeEmailSend)),
asynq.MaxRetry(constants.DefaultRetryMax),
)

View File

@@ -126,9 +126,9 @@ func (s *Service) CreateTask(ctx context.Context, req *dto.CreateExportTaskReque
ctx,
constants.TaskTypeExportDispatch,
dispatchPayload{TaskID: task.ID},
asynq.Queue(constants.QueueDefault),
asynq.MaxRetry(constants.ExportDispatchRetryMax),
asynq.Timeout(constants.ExportDispatchTaskTimeout),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeExportDispatch)),
); err != nil {
_ = s.taskStore.MarkFailed(ctx, task.ID, userID, "导出任务入队失败")
return nil, errors.Wrap(errors.CodeTaskQueueError, err, "导出任务入队失败")

View File

@@ -13,6 +13,7 @@ import (
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/hibiken/asynq"
"gorm.io/gorm"
)
@@ -108,7 +109,12 @@ func (s *Service) CreateImportTask(ctx context.Context, req *dto.ImportIotCardRe
}
payload := IotCardImportPayload{TaskID: task.ID}
err = s.queueClient.EnqueueTask(ctx, constants.TaskTypeIotCardImport, payload)
err = s.queueClient.EnqueueTask(
ctx,
constants.TaskTypeIotCardImport,
payload,
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeIotCardImport)),
)
if err != nil {
s.importTaskStore.UpdateStatus(ctx, task.ID, model.ImportTaskStatusFailed, "任务入队失败: "+err.Error())
appErr := errors.Wrap(errors.CodeInternalError, err, "任务入队失败")

View File

@@ -169,8 +169,8 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, paymentNo string, p
if len(linkedIDs) > 0 {
taskPayload := task.AutoPurchasePayload{RechargeOrderID: rechargeOrder.ID}
if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeAutoPurchaseAfterRecharge, taskPayload,
asynq.Queue(constants.QueueDefault),
asynq.MaxRetry(3),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeAutoPurchaseAfterRecharge)),
); err != nil {
s.logger.Error("自动购包任务入队失败",
zap.Uint("recharge_order_id", rechargeOrder.ID),

View File

@@ -271,8 +271,8 @@ func (h *AutoPurchaseHandler) ProcessTask(ctx context.Context, task *asynq.Task)
zap.Error(marshalErr))
} else {
commissionTask := asynq.NewTask(constants.TaskTypeCommission, payloadBytes,
asynq.Queue(constants.QueueLow),
asynq.MaxRetry(3),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeCommission)),
)
if _, enqueueErr := h.asynqClient.EnqueueContext(ctx, commissionTask); enqueueErr != nil {
h.logger.Warn("自动购包后提交佣金任务失败",
@@ -296,7 +296,7 @@ func NewAutoPurchaseTask(rechargeOrderID uint) (*asynq.Task, error) {
return asynq.NewTask(constants.TaskTypeAutoPurchaseAfterRecharge, payloadBytes,
asynq.MaxRetry(3),
asynq.Timeout(2*time.Minute),
asynq.Queue(constants.QueueDefault),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeAutoPurchaseAfterRecharge)),
), nil
}

View File

@@ -50,6 +50,7 @@ func enqueueTask(ctx context.Context, client *asynq.Client, taskType string, pay
return err
}
opts = append(opts, asynq.Queue(constants.QueueForTaskType(taskType)))
task := asynq.NewTask(taskType, bytes, opts...)
_, err = client.EnqueueContext(ctx, task)
return err

View File

@@ -215,9 +215,9 @@ func (h *ExportDispatchHandler) enqueueShardTasks(ctx context.Context, task *mod
h.asynqClient,
constants.TaskTypeExportShard,
payload,
asynq.Queue(constants.QueueLow),
asynq.MaxRetry(constants.ExportShardRetryMax),
asynq.Timeout(constants.ExportShardTaskTimeout),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeExportShard)),
)
if err != nil {
h.logger.Error("导出分片任务入队失败",
@@ -237,10 +237,10 @@ func (h *ExportDispatchHandler) enqueueFinalizeTask(ctx context.Context, taskID
h.asynqClient,
constants.TaskTypeExportFinalize,
ExportFinalizePayload{TaskID: taskID},
asynq.Queue(constants.QueueDefault),
asynq.MaxRetry(constants.ExportFinalizeRetryMax),
asynq.Timeout(constants.ExportFinalizeTaskTimeout),
asynq.ProcessIn(5*time.Second),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeExportFinalize)),
)
}

View File

@@ -175,9 +175,9 @@ func (h *ExportShardHandler) enqueueFinalize(ctx context.Context, taskID uint) e
h.asynqClient,
constants.TaskTypeExportFinalize,
ExportFinalizePayload{TaskID: taskID},
asynq.Queue(constants.QueueDefault),
asynq.MaxRetry(constants.ExportFinalizeRetryMax),
asynq.Timeout(constants.ExportFinalizeTaskTimeout),
asynq.ProcessIn(2*time.Second),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeExportFinalize)),
)
}

View File

@@ -206,7 +206,7 @@ func (h *PollingRealnameHandler) triggerFirstRealnameActivation(ctx context.Cont
task := asynq.NewTask(constants.TaskTypePackageFirstActivation, payloadBytes,
asynq.MaxRetry(3),
asynq.Timeout(30*time.Second),
asynq.Queue(constants.QueueDefault),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypePackageFirstActivation)),
)
if _, err := h.asynqClient.EnqueueContext(ctx, task); err != nil {
h.base.logger.Warn("提交首次实名激活任务失败", zap.Uint("card_id", cardID), zap.Error(err))
@@ -244,7 +244,7 @@ func (h *PollingRealnameHandler) triggerDeviceRealnameActivation(ctx context.Con
task := asynq.NewTask(constants.TaskTypePackageFirstActivation, payloadBytes,
asynq.MaxRetry(3),
asynq.Timeout(30*time.Second),
asynq.Queue(constants.QueueDefault),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypePackageFirstActivation)),
)
if _, err := h.asynqClient.EnqueueContext(ctx, task); err != nil {
h.base.logger.Warn("提交设备实名激活任务失败",