mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package messaging
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/cryptoniumX/mpcium/pkg/logger"
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
)
|
|
|
|
var (
|
|
ErrPermament = errors.New("Permanent messaging error")
|
|
)
|
|
|
|
type MessageQueue interface {
|
|
Enqueue(topic string, message []byte, options *EnqueueOptions) error
|
|
Dequeue(topic string, handler func(message []byte) error) error
|
|
Close()
|
|
}
|
|
|
|
type EnqueueOptions struct {
|
|
IdempotententKey string
|
|
}
|
|
|
|
type msgQueue struct {
|
|
consumerName string
|
|
js jetstream.JetStream
|
|
consumer jetstream.Consumer
|
|
consumerContext jetstream.ConsumeContext
|
|
}
|
|
|
|
type NATsMessageQueueManager struct {
|
|
queueName string
|
|
js jetstream.JetStream
|
|
}
|
|
|
|
func NewNATsMessageQueueManager(queueName string, subjectWildCards []string, nc *nats.Conn) *NATsMessageQueueManager {
|
|
js, err := jetstream.New(nc)
|
|
if err != nil {
|
|
logger.Fatal("Error creating JetStream context: ", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
stream, err := js.Stream(ctx, queueName)
|
|
if err != nil {
|
|
logger.Warn("Stream not found, creating new stream", "stream", queueName)
|
|
}
|
|
if stream != nil {
|
|
info, _ := stream.Info(ctx)
|
|
logger.Info("Stream found", "info", info)
|
|
|
|
}
|
|
|
|
_, err = js.CreateOrUpdateStream(context.Background(), jetstream.StreamConfig{
|
|
Name: queueName,
|
|
Description: "Stream for " + queueName,
|
|
Subjects: subjectWildCards,
|
|
MaxBytes: 1024,
|
|
Storage: jetstream.FileStorage,
|
|
Retention: jetstream.WorkQueuePolicy,
|
|
})
|
|
if err != nil {
|
|
logger.Fatal("Error creating JetStream stream: ", err)
|
|
}
|
|
logger.Info("Creating apex NATs Jetstream context successfully!")
|
|
|
|
return &NATsMessageQueueManager{
|
|
queueName: queueName,
|
|
js: js,
|
|
}
|
|
}
|
|
|
|
func (m *NATsMessageQueueManager) NewMessageQueue(consumerName string) MessageQueue {
|
|
mq := &msgQueue{
|
|
consumerName: consumerName,
|
|
js: m.js,
|
|
}
|
|
consumerWildCard := fmt.Sprintf("%s.%s.*", m.queueName, consumerName)
|
|
cfg := jetstream.ConsumerConfig{
|
|
Name: consumerName,
|
|
Durable: consumerName,
|
|
MaxAckPending: 4,
|
|
FilterSubjects: []string{
|
|
consumerWildCard,
|
|
},
|
|
MaxDeliver: 3,
|
|
}
|
|
logger.Info("Creating consumer for subject", "config", cfg)
|
|
consumer, err := m.js.CreateOrUpdateConsumer(context.Background(), m.queueName, cfg)
|
|
if err != nil {
|
|
logger.Fatal("Error creating JetStream consumer: ", err)
|
|
}
|
|
|
|
mq.consumer = consumer
|
|
return mq
|
|
}
|
|
|
|
func (mq *msgQueue) Enqueue(topic string, message []byte, options *EnqueueOptions) error {
|
|
header := nats.Header{}
|
|
if options != nil {
|
|
header.Add("Nats-Msg-Id", options.IdempotententKey)
|
|
}
|
|
|
|
logger.Info("Publishing message", "topic", topic)
|
|
_, err := mq.js.PublishMsg(context.Background(), &nats.Msg{
|
|
Subject: topic,
|
|
Data: message,
|
|
Header: header,
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Error enqueueing message: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (mq *msgQueue) Dequeue(topic string, handler func(message []byte) error) error {
|
|
c, err := mq.consumer.Consume(func(msg jetstream.Msg) {
|
|
meta, _ := msg.Metadata()
|
|
logger.Info("Received message", "meta", meta)
|
|
err := handler(msg.Data())
|
|
if err != nil {
|
|
if errors.Is(err, ErrPermament) {
|
|
logger.Info("Permanent error on message", "meta", meta)
|
|
msg.Term()
|
|
return
|
|
}
|
|
|
|
logger.Error("Error handling message: ", err)
|
|
msg.Nak()
|
|
return
|
|
}
|
|
|
|
logger.Info("Message Acknowledged", "meta", meta)
|
|
err = msg.Ack()
|
|
if err != nil {
|
|
logger.Error("Error acknowledging message: ", err)
|
|
}
|
|
})
|
|
mq.consumerContext = c
|
|
return err
|
|
}
|
|
|
|
func (mq *msgQueue) Close() {
|
|
mq.consumerContext.Stop()
|
|
}
|
|
|
|
func (n *msgQueue) handleReconnect(nc *nats.Conn) {
|
|
logger.Info("NATS: Reconnected to NATS")
|
|
}
|