topfans/backend/services/assetService/mq/producer.go
zerosaturation a9ce281d5e feat(asset): emit task:event on mint success (fix daily_mint 悬空)
assetService 接入 MQ producer:铸造成功时 emit `task:event { event_type: daily_mint }`,
由 taskService consumer 异步调 ProcessTaskEvent 完成判定。

- main.go: 初始化 MQ (Asynq producer-only),沿用 galleryService 模式;
  失败仅 Warn 不阻塞主路径
- service/mint_service.go: CreateMintOrder 成功分支 fire-and-forget emit
- mq/producer.go: 新增 EnqueueTaskEvent helper,封装 TaskEventPayload marshal +
  adapter.TaskProducer.Enqueue

配套:spec §4 / Phase F.1 / impl plan Phase D。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 15:45:42 +08:00

56 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package mq 是 assetService 的消息队列适配入口producer-only
//
// 业务侧调用示例 (mint_service.CreateMintOrder 成功分支):
//
// assetmq.EnqueueTaskEvent(ctx, userID, starID, tasks.EventDailyMint)
//
// 全部走 pkg/mq/adapter不直接 import asynq 或 redis-streams 包。
// assetService 是 producer-only不注册 handler / 不起 consumer ——
// task:event 消息由 taskService 的 mq/consumer.go 异步消费处理。
package mq
import (
"context"
"fmt"
"github.com/topfans/backend/pkg/logger"
"github.com/topfans/backend/pkg/mq/adapter"
"github.com/topfans/backend/pkg/mq/tasks"
queueconsts "github.com/topfans/backend/pkg/queue/consts"
"go.uber.org/zap"
)
// EnqueueTaskEvent 业务事件 emitspec §4 / Phase F.1)。
//
// 修复 daily_mint 悬空:铸造成功时 emit `task:event { event_type: daily_mint }`
// 由 taskService 的 MQ consumer 异步调 DailyTaskService.ProcessTaskEvent 完成判定。
// 失败仅 Warn 日志不阻塞主路径fire-and-forget与现有 EnqueueExhibitionExpire 一致)。
func EnqueueTaskEvent(ctx context.Context, userID, starID int64, eventType string) error {
payload, err := tasks.MarshalToPayload(tasks.TaskEventPayload{
UserID: userID,
StarID: starID,
EventType: eventType,
})
if err != nil {
return fmt.Errorf("asset mq: marshal task event payload: %w", err)
}
task := adapter.Task{
Queue: queueconsts.QueueDefault, // taskService consumer 注册到 default 队列
Type: tasks.TypeTaskEvent,
Payload: payload,
MaxRetry: 3,
}
if _, err := adapter.Get().TaskProducer().Enqueue(ctx, task); err != nil {
logger.Logger.Warn("enqueue task:event failed",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
zap.String("event_type", eventType),
zap.Error(err))
return err
}
logger.Logger.Info("task:event enqueued",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
zap.String("event_type", eventType))
return nil
}