package worker import ( "context" "encoding/json" "errors" "fmt" db "github.com/FernandoJVideira/api_tmpl/internal/db/sqlc" "github.com/FernandoJVideira/api_tmpl/internal/mailer" "github.com/FernandoJVideira/api_tmpl/pkg/testutil" "github.com/hibiken/asynq" "github.com/rs/zerolog/log" ) const TaskSendVerifyEmail = "task:send_verify_email" type SendVerifyEmailPayload struct { Username string `json:"username"` } func (r *RedisTaskDistributor) DestributeTaskSendVerifyEmail(ctx context.Context, payload *SendVerifyEmailPayload, opts ...asynq.Option) error { jsonPayload, err := json.Marshal(payload) if err != nil { return fmt.Errorf("failed to marshal SendVerifyEmailPayload: %w", err) } task := asynq.NewTask(TaskSendVerifyEmail, jsonPayload, opts...) info, err := r.client.EnqueueContext(ctx, task) if err != nil { return fmt.Errorf("failed to enqueue task %s: %w", TaskSendVerifyEmail, err) } log.Info().Str("type", task.Type()).Bytes("payload", task.Payload()).Str("queue", info.Queue).Int("max_retries", info.MaxRetry).Msgf("enqueued task") return nil } func (r *RedisTaskProcessor) ProcessTaskSendVerifyEmail(ctx context.Context, task *asynq.Task) error { var payload SendVerifyEmailPayload if err := json.Unmarshal(task.Payload(), &payload); err != nil { return fmt.Errorf("failed to unmarshal payload: %w", asynq.SkipRetry) } usr, err := r.store.GetUser(ctx, payload.Username) if err != nil { if errors.Is(err, db.ErrRecordNotFound) { return fmt.Errorf("user %s not found: %w", payload.Username, asynq.SkipRetry) } return fmt.Errorf("failed to get user %s: %w", payload.Username, err) } verifyEmail, err := r.store.CreateVerifyEmail(ctx, db.CreateVerifyEmailParams{ Username: usr.Username, Email: usr.Email, SecretCode: testutil.RandomString(32), }) if err != nil { return fmt.Errorf("failed to create verify email for user %s: %w", usr.Username, err) } vars := struct { ServiceName string Username string ActivationURL string }{ ServiceName: r.config.ServiceName, Username: usr.Username, ActivationURL: fmt.Sprintf("%s/verify_email?id=%d&code=%s", r.config.FrontendURL, verifyEmail.ID, verifyEmail.SecretCode), } to := []string{usr.Email} err = r.mailer.Send(mailer.UserWelcomeTemplate, vars, to, nil, nil, nil) if err != nil { return fmt.Errorf("failed to send verify email to user %s: %w", usr.Username, err) } log.Info().Str("type", task.Type()).Bytes("payload", task.Payload()).Str("email", usr.Email).Msg("sent verify email to user") return nil }