eventRT/mq/mq_init.go

102 lines
2.3 KiB
Go
Raw Normal View History

2026-01-29 16:54:00 +08:00
// Package mq define message queue operation functions
package mq
import (
2026-01-30 17:43:16 +08:00
"context"
2026-01-29 16:54:00 +08:00
"fmt"
2026-01-30 17:43:16 +08:00
"net/url"
"sync"
"time"
2026-01-29 16:54:00 +08:00
"eventRT/config"
2026-01-30 17:43:16 +08:00
"eventRT/logger"
2026-01-29 16:54:00 +08:00
2026-01-30 17:43:16 +08:00
amqp "github.com/rabbitmq/amqp091-go"
2026-01-29 16:54:00 +08:00
)
2026-01-30 17:43:16 +08:00
var (
_globalRabbitMQProxy *RabbitMQProxy
rabbitMQOnce sync.Once
)
// RabbitMQProxy define stuct of rabbitMQ connection proxy
type RabbitMQProxy struct {
Conn *amqp.Connection
mu sync.Mutex
}
// GetConn define func to return the rabbitMQ connection
func GetConn() *amqp.Connection {
_globalRabbitMQProxy.mu.Lock()
defer _globalRabbitMQProxy.mu.Unlock()
return _globalRabbitMQProxy.Conn
}
// InitRabbitProxy return instance of rabbitMQ connection
func InitRabbitProxy(ctx context.Context, rCfg config.RabbitMQConfig) *RabbitMQProxy {
amqpURI := generateRabbitMQURI(rCfg)
rabbitMQOnce.Do(func() {
conn := initRabbitMQ(ctx, amqpURI)
_globalRabbitMQProxy = &RabbitMQProxy{Conn: conn}
go _globalRabbitMQProxy.handleReconnect(ctx, amqpURI)
})
return _globalRabbitMQProxy
}
// initRabbitMQ return instance of rabbitMQ connection
func initRabbitMQ(ctx context.Context, rabbitMQURI string) *amqp.Connection {
logger.Info(ctx, fmt.Sprintf("connecting to rabbitMQ server at: %s", rabbitMQURI))
conn, err := amqp.Dial(rabbitMQURI)
2026-01-29 16:54:00 +08:00
if err != nil {
2026-01-30 17:43:16 +08:00
panic(fmt.Errorf("failed to connect to rabbitMQ: %w", err))
2026-01-29 16:54:00 +08:00
}
2026-01-30 17:43:16 +08:00
2026-01-29 16:54:00 +08:00
return conn
}
2026-01-30 17:43:16 +08:00
func (p *RabbitMQProxy) handleReconnect(ctx context.Context, rabbitMQURI string) {
for {
closeChan := make(chan *amqp.Error)
2026-02-04 17:43:52 +08:00
GetConn().NotifyClose(closeChan)
2026-01-30 17:43:16 +08:00
err, ok := <-closeChan
if !ok {
logger.Info(ctx, "rabbitMQ notify channel closed, stopping solicitor")
break
}
if err != nil {
logger.Warn(ctx, "rabbitMQ connection closed by error", "reason", err)
} else {
logger.Info(ctx, "rabbitMQ connection closed normally (nil err)")
}
for {
time.Sleep(5 * time.Second)
newConn, err := amqp.Dial(rabbitMQURI)
if err == nil {
p.mu.Lock()
p.Conn = newConn
p.mu.Unlock()
logger.Info(ctx, "rabbitMQ reconnected successfully")
break
}
logger.Error(ctx, "rabbitMQ reconnect failed", "err", err)
}
}
}
func generateRabbitMQURI(rCfg config.RabbitMQConfig) string {
user := url.QueryEscape(rCfg.User)
password := url.QueryEscape(rCfg.Password)
amqpURI := fmt.Sprintf("amqp://%s:%s@%s:%d/",
user,
password,
rCfg.Host,
rCfg.Port,
)
return amqpURI
}