Files
VLoop/backend/internal/middleware/rabbitmq/rabbitMQ.go
hhs e3c68dd6d3
Some checks failed
CI / Backend (push) Has been cancelled
CI / Frontend (push) Has been cancelled
docs: 添加部分注释
2026-07-01 19:34:13 +08:00

124 lines
2.6 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 rabbitmq
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"errors"
"feedsystem_video_go/internal/config"
"log"
"strconv"
"time"
amqp "github.com/rabbitmq/amqp091-go"
)
// RabbitMQ 只管理 ConnectionChannel 由各组件按需创建
type RabbitMQ struct {
Conn *amqp.Connection
}
func NewRabbitMQ(cfg *config.RabbitMQConfig) (*RabbitMQ, error) {
if cfg == nil {
return nil, errors.New("rabbitmq config is nil")
}
url := "amqp://" + cfg.Username + ":" + cfg.Password + "@" + cfg.Host + ":" + strconv.Itoa(cfg.Port) + "/"
conn, err := amqp.Dial(url)
if err != nil {
return nil, err
}
return &RabbitMQ{Conn: conn}, nil
}
func (r *RabbitMQ) Close() error {
if r == nil {
return nil
}
if r.Conn != nil {
return r.Conn.Close()
}
return nil
}
func (r *RabbitMQ) NewChannel() (*amqp.Channel, error) {
if r == nil || r.Conn == nil {
return nil, errors.New("rabbitmq connection is not initialized")
}
return r.Conn.Channel()
}
func DeclareTopic(ch *amqp.Channel, exchange string, queue string, bindingKey string) error {
if ch == nil {
return errors.New("channel is not initialized")
}
if exchange == "" || queue == "" || bindingKey == "" {
return errors.New("exchange/queue/bindingKey is required")
}
if err := ch.ExchangeDeclare(
exchange,
"topic",
true, // 持久化参数
false, // autoDelete 是否在未使用时自动删除
false, // internal 是否交给其他交换机用而不直接收消息
false, // noWait 是否不等待 broker 确认
nil,
); err != nil {
return err
}
q, err := ch.QueueDeclare(
queue,
true,
false,
false,
false,
amqp.Table{"x-dead-letter-exchange": DLXExchange},
)
if err != nil {
return err
}
if err := ch.QueueBind(
q.Name,
bindingKey,
exchange,
false,
nil,
); err != nil {
return err
}
if err := DeclareDLX(ch, queue); err != nil {
log.Printf("DLX declare failed for %s: %v", queue, err)
}
return nil
}
func PublishJSON(ctx context.Context, ch *amqp.Channel, exchange string, routingKey string, payload any) error {
if ch == nil {
return errors.New("channel is not initialized")
}
if exchange == "" || routingKey == "" {
return errors.New("exchange and routingKey are required")
}
b, err := json.Marshal(payload)
if err != nil {
return err
}
return ch.PublishWithContext(ctx, exchange, routingKey, false, false, amqp.Publishing{
ContentType: "application/json",
DeliveryMode: amqp.Persistent,
Timestamp: time.Now(),
Body: b,
})
}
func newEventID(n int) (string, error) {
b := make([]byte, n)
if _, err := rand.Read(b); err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}