package email import ( "context" "fmt" "github.com/break/junhong_cmp_fiber/internal/task" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/queue" "github.com/bytedance/sonic" "github.com/hibiken/asynq" "go.uber.org/zap" ) // Service 邮件服务 type Service struct { queueClient *queue.Client logger *zap.Logger } // NewService 创建邮件服务实例 func NewService(queueClient *queue.Client, logger *zap.Logger) *Service { return &Service{ queueClient: queueClient, logger: logger, } } // SendWelcomeEmail 发送欢迎邮件(异步) func (s *Service) SendWelcomeEmail(ctx context.Context, userID uint, email string) error { // 构造任务载荷 payload := &task.EmailPayload{ RequestID: fmt.Sprintf("welcome-%d", userID), To: email, Subject: "欢迎加入君鸿卡管系统", 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 fmt.Errorf("序列化邮件任务载荷失败: %w", err) } // 提交任务到队列 err = s.queueClient.EnqueueTask( ctx, constants.TaskTypeEmailSend, payloadBytes, asynq.Queue(constants.QueueDefault), asynq.MaxRetry(constants.DefaultRetryMax), ) if err != nil { s.logger.Error("提交欢迎邮件任务失败", zap.Uint("user_id", userID), zap.String("email", email), zap.Error(err)) return fmt.Errorf("提交欢迎邮件任务失败: %w", err) } s.logger.Info("欢迎邮件任务已提交", zap.Uint("user_id", userID), zap.String("email", email)) return nil } // SendPasswordResetEmail 发送密码重置邮件(异步) func (s *Service) SendPasswordResetEmail(ctx context.Context, email string, resetToken string) error { // 构造任务载荷 payload := &task.EmailPayload{ RequestID: fmt.Sprintf("reset-%s-%s", email, resetToken), To: email, Subject: "密码重置请求", 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 fmt.Errorf("序列化密码重置邮件任务载荷失败: %w", err) } // 提交任务到队列(高优先级) err = s.queueClient.EnqueueTask( ctx, constants.TaskTypeEmailSend, payloadBytes, asynq.Queue(constants.QueueCritical), // 密码重置使用高优先级队列 asynq.MaxRetry(constants.DefaultRetryMax), ) if err != nil { s.logger.Error("提交密码重置邮件任务失败", zap.String("email", email), zap.Error(err)) return fmt.Errorf("提交密码重置邮件任务失败: %w", err) } s.logger.Info("密码重置邮件任务已提交", zap.String("email", email)) return nil } // SendNotificationEmail 发送通知邮件(异步) func (s *Service) SendNotificationEmail(ctx context.Context, to string, subject string, body string) error { // 构造任务载荷 payload := &task.EmailPayload{ RequestID: fmt.Sprintf("notify-%s-%d", to, getCurrentTimestamp()), To: to, Subject: subject, Body: body, } payloadBytes, err := sonic.Marshal(payload) if err != nil { s.logger.Error("序列化通知邮件任务载荷失败", zap.String("to", to), zap.Error(err)) return fmt.Errorf("序列化通知邮件任务载荷失败: %w", err) } // 提交任务到队列(低优先级) err = s.queueClient.EnqueueTask( ctx, constants.TaskTypeEmailSend, payloadBytes, asynq.Queue(constants.QueueLow), // 通知邮件使用低优先级队列 asynq.MaxRetry(constants.DefaultRetryMax), ) if err != nil { s.logger.Error("提交通知邮件任务失败", zap.String("to", to), zap.Error(err)) return fmt.Errorf("提交通知邮件任务失败: %w", err) } s.logger.Info("通知邮件任务已提交", zap.String("to", to), zap.String("subject", subject)) return nil } // getCurrentTimestamp 获取当前时间戳(毫秒) func getCurrentTimestamp() int64 { return 0 // 实际实现应返回真实时间戳 }