package queueing import ( "context" "log/slog" "gorm.io/gorm" "wucher/internal/config" "wucher/internal/queue" mysqlrepo "wucher/internal/repository/mysql" sqsrepo "wucher/internal/repository/sqs" "wucher/internal/resilience" ) func NewEmailProducer( ctx context.Context, queueCfg config.QueueConfig, sqsCfg config.SQSConfig, executor *resilience.Executor, logger *slog.Logger, ) (queue.EmailJobProducer, error) { producer, err := NewQueueProducer(ctx, sqsCfg, executor, "api") if err != nil { return nil, err } return queue.NewEmailEnqueuer(NewOutboxSerializer(queueCfg, sqsCfg), producer, logger), nil } func NewQueueProducer(ctx context.Context, sqsCfg config.SQSConfig, executor *resilience.Executor, component string) (queue.QueueProducer, error) { client, err := sqsrepo.NewClient(ctx, sqsCfg) if err != nil { return nil, err } return sqsrepo.NewQueue( sqsrepo.NewResilientAPI(client, executor), sqsCfg, sqsrepo.WithMetricsComponent(component), ) } func NewOutboxSerializer(queueCfg config.QueueConfig, sqsCfg config.SQSConfig) queue.MessageSerializer { return queue.NewJSONSerializer( queueCfg.MessageSchemaVersion, queueCfg.EnableLegacyPayloadFallback, sqsCfg.QueueType, sqsCfg.MessageGroupID, ) } func NewEmailConsumer( ctx context.Context, queueCfg config.QueueConfig, sqsCfg config.SQSConfig, executor *resilience.Executor, ) (queue.QueueConsumer, queue.MessageSerializer, error) { client, err := sqsrepo.NewClient(ctx, sqsCfg) if err != nil { return nil, nil, err } consumer, err := sqsrepo.NewEmailQueue( sqsrepo.NewResilientAPI(client, executor), sqsCfg, sqsrepo.WithMetricsComponent("email_worker"), ) if err != nil { return nil, nil, err } serializer := queue.NewJSONSerializer( queueCfg.MessageSchemaVersion, queueCfg.EnableLegacyPayloadFallback, sqsCfg.QueueType, sqsCfg.MessageGroupID, ) return consumer, serializer, nil } func NewFileProcessingProducer( ctx context.Context, queueCfg config.FileQueueConfig, sqsCfg config.SQSConfig, executor *resilience.Executor, logger *slog.Logger, ) (queue.FileProcessingJobProducer, error) { producer, err := NewQueueProducer(ctx, sqsCfg, executor, "api") if err != nil { return nil, err } return queue.NewFileProcessingEnqueuer(NewFileProcessingSerializer(queueCfg, sqsCfg), producer, logger), nil } func NewFileProcessingSerializer(queueCfg config.FileQueueConfig, sqsCfg config.SQSConfig) queue.FileProcessingMessageSerializer { return queue.NewFileProcessingJSONSerializer( queueCfg.MessageSchemaVersion, sqsCfg.QueueType, sqsCfg.MessageGroupID, ) } func NewFileProcessingConsumer( ctx context.Context, queueCfg config.FileQueueConfig, sqsCfg config.SQSConfig, executor *resilience.Executor, ) (queue.QueueConsumer, queue.FileProcessingMessageSerializer, error) { client, err := sqsrepo.NewClient(ctx, sqsCfg) if err != nil { return nil, nil, err } consumer, err := sqsrepo.NewQueue( sqsrepo.NewResilientAPI(client, executor), sqsCfg, sqsrepo.WithMetricsComponent("file_worker"), ) if err != nil { return nil, nil, err } serializer := queue.NewFileProcessingJSONSerializer( queueCfg.MessageSchemaVersion, sqsCfg.QueueType, sqsCfg.MessageGroupID, ) return consumer, serializer, nil } func NewIdempotencyStore(db *gorm.DB, queueCfg config.QueueConfig) queue.IdempotencyStore { if db == nil { return queue.NewMemoryIdempotencyStore() } return mysqlrepo.NewQueueIdempotencyStore(db, queueCfg.IdempotencyKeyPrefix) } func NewIdempotencyStoreWithPrefix(db *gorm.DB, keyPrefix string) queue.IdempotencyStore { if db == nil { return queue.NewMemoryIdempotencyStore() } return mysqlrepo.NewQueueIdempotencyStore(db, keyPrefix) }