modelRT/mq/publish_up_down_limit_event.go

147 lines
4.3 KiB
Go
Raw Normal View History

2026-02-03 17:05:32 +08:00
// Package mq provides read or write access to message queue services
package mq
import (
"context"
2026-03-02 17:00:09 +08:00
"encoding/json"
2026-02-03 17:05:32 +08:00
"time"
"modelRT/constants"
2026-02-03 17:05:32 +08:00
"modelRT/logger"
2026-03-02 17:00:09 +08:00
"modelRT/mq/event"
2026-02-03 17:05:32 +08:00
amqp "github.com/rabbitmq/amqp091-go"
)
// MsgChan define variable of channel to store messages that need to be sent to rabbitMQ
2026-03-02 17:00:09 +08:00
var MsgChan chan *event.EventRecord
func init() {
2026-03-02 17:00:09 +08:00
MsgChan = make(chan *event.EventRecord, 10000)
}
func initUpDownLimitEventChannel(ctx context.Context) (*amqp.Channel, error) {
2026-02-03 17:05:32 +08:00
var channel *amqp.Channel
var err error
channel, err = GetConn().Channel()
if err != nil {
logger.Error(ctx, "open rabbitMQ server channel failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
err = channel.ExchangeDeclare(constants.EventDeadExchangeName, "topic", true, false, false, false, nil)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "declare event dead letter exchange failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
_, err = channel.QueueDeclare(constants.EventUpDownDeadQueueName, true, false, false, false, nil)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "declare event dead letter queue failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
2026-03-02 17:00:09 +08:00
err = channel.QueueBind(constants.EventUpDownDeadQueueName, "#", constants.EventDeadExchangeName, false, nil)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "bind event dead letter queue with routing key and exchange failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
err = channel.ExchangeDeclare(constants.EventExchangeName, "topic", true, false, false, false, nil)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "declare event exchange failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
args := amqp.Table{
"x-max-length": int32(50),
"x-dead-letter-exchange": constants.EventDeadExchangeName,
"x-dead-letter-routing-key": constants.EventUpDownDeadRoutingKey,
2026-02-03 17:05:32 +08:00
}
_, err = channel.QueueDeclare(constants.EventUpDownQueueName, true, false, false, false, args)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "declare event queue failed", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
err = channel.QueueBind(constants.EventUpDownQueueName, constants.EventUpDownRoutingKey, constants.EventExchangeName, false, nil)
2026-02-03 17:05:32 +08:00
if err != nil {
2026-03-02 17:00:09 +08:00
logger.Error(ctx, "bind event queue with routing key and exchange failed", "error", err)
return nil, err
2026-02-03 17:05:32 +08:00
}
if err := channel.Confirm(false); err != nil {
logger.Error(ctx, "channel could not be put into confirm mode", "error", err)
2026-03-02 17:00:09 +08:00
return nil, err
2026-02-03 17:05:32 +08:00
}
return channel, nil
}
// PushUpDownLimitEventToRabbitMQ define func to push up and down limit event message to rabbitMQ
2026-03-02 17:00:09 +08:00
func PushUpDownLimitEventToRabbitMQ(ctx context.Context, msgChan chan *event.EventRecord) {
channel, err := initUpDownLimitEventChannel(ctx)
2026-02-03 17:05:32 +08:00
if err != nil {
logger.Error(ctx, "initializing rabbitMQ channel failed", "error", err)
return
}
// TODO 使用配置修改确认模式通道参数
confirms := channel.NotifyPublish(make(chan amqp.Confirmation, 100))
go func() {
for {
select {
case confirm, ok := <-confirms:
if !ok {
return
}
if !confirm.Ack {
logger.Error(ctx, "publish message failed (rejected by rabbitMQ)", "tag", confirm.DeliveryTag)
}
case <-ctx.Done():
return
}
}
}()
for {
select {
case <-ctx.Done():
logger.Info(ctx, "push event alarm message to rabbitMQ stopped by context cancel")
channel.Close()
return
2026-03-02 17:00:09 +08:00
case eventRecord, ok := <-msgChan:
2026-02-03 17:05:32 +08:00
if !ok {
logger.Info(ctx, "push event alarm message to rabbitMQ stopped by msgChan closed, exiting push loop")
channel.Close()
return
}
2026-03-02 17:00:09 +08:00
// TODO 将消息的序列化移动到发送之前以便使用eventRecord的category来作为routing key
recordBytes, err := json.Marshal(eventRecord)
if err != nil {
logger.Error(ctx, "marshal event record failed", "event_uuid", eventRecord.EventUUID, "error", err)
continue
}
2026-02-03 17:05:32 +08:00
// send event alarm message to rabbitMQ queue
2026-03-02 17:00:09 +08:00
routingKey := eventRecord.Category
2026-02-03 17:05:32 +08:00
pubCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
err = channel.PublishWithContext(pubCtx,
2026-03-02 17:00:09 +08:00
constants.EventExchangeName, // exchange
routingKey, // routing key
false, // mandatory
false, // immediate
2026-02-03 17:05:32 +08:00
amqp.Publishing{
ContentType: "text/plain",
2026-03-02 17:00:09 +08:00
Body: recordBytes,
2026-02-03 17:05:32 +08:00
})
cancel()
if err != nil {
2026-03-02 17:00:09 +08:00
logger.Error(ctx, "publish message to rabbitMQ queue failed", "message", recordBytes, "error", err)
2026-02-03 17:05:32 +08:00
}
}
}
}