rwadurian/backend/mpc-system/services/account/adapters/output/rabbitmq/event_publisher.go

81 lines
1.6 KiB
Go

package rabbitmq
import (
"context"
"encoding/json"
"time"
amqp "github.com/rabbitmq/amqp091-go"
"github.com/rwadurian/mpc-system/services/account/application/ports"
)
const (
exchangeName = "account.events"
exchangeType = "topic"
)
// EventPublisherAdapter implements EventPublisher using RabbitMQ
type EventPublisherAdapter struct {
conn *amqp.Connection
channel *amqp.Channel
}
// NewEventPublisherAdapter creates a new EventPublisherAdapter
func NewEventPublisherAdapter(conn *amqp.Connection) (*EventPublisherAdapter, error) {
channel, err := conn.Channel()
if err != nil {
return nil, err
}
// Declare exchange
err = channel.ExchangeDeclare(
exchangeName,
exchangeType,
true, // durable
false, // auto-deleted
false, // internal
false, // no-wait
nil, // arguments
)
if err != nil {
channel.Close()
return nil, err
}
return &EventPublisherAdapter{
conn: conn,
channel: channel,
}, nil
}
// Publish publishes an account event
func (p *EventPublisherAdapter) Publish(ctx context.Context, event ports.AccountEvent) error {
body, err := json.Marshal(event)
if err != nil {
return err
}
routingKey := string(event.Type)
return p.channel.PublishWithContext(ctx,
exchangeName,
routingKey,
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "application/json",
DeliveryMode: amqp.Persistent,
Timestamp: time.Now().UTC(),
Body: body,
},
)
}
// Close closes the publisher
func (p *EventPublisherAdapter) Close() error {
if p.channel != nil {
return p.channel.Close()
}
return nil
}