service backend
This commit is contained in:
87
api/pkg/messaging/internal/inprocess/broker.go
Normal file
87
api/pkg/messaging/internal/inprocess/broker.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package inprocess
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
me "github.com/tech/sendico/pkg/messaging/envelope"
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type MessageBroker struct {
|
||||
logger mlogger.Logger
|
||||
subscribers map[string][]chan me.Envelope
|
||||
lock sync.RWMutex
|
||||
bufferSize int
|
||||
}
|
||||
|
||||
func (b *MessageBroker) Publish(envelope me.Envelope) error {
|
||||
topic := envelope.GetSignature().ToString()
|
||||
b.logger.Debug("Publishing message", mzap.Envelope(envelope))
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
if subs, ok := b.subscribers[topic]; ok {
|
||||
for _, sub := range subs {
|
||||
select {
|
||||
case sub <- envelope:
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
b.logger.Warn("Topic not found", mzap.Envelope(envelope))
|
||||
return merrors.NoMessagingTopic(topic)
|
||||
}
|
||||
|
||||
func (b *MessageBroker) Subscribe(event model.NotificationEvent) (<-chan me.Envelope, error) {
|
||||
topic := event.ToString()
|
||||
b.logger.Info("New topic subscriber", zap.String("topic", topic))
|
||||
ch := make(chan me.Envelope, b.bufferSize) // Buffered channel to avoid blocking publishers
|
||||
{
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
b.subscribers[topic] = append(b.subscribers[topic], ch)
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (b *MessageBroker) Unsubscribe(event model.NotificationEvent, subChan <-chan me.Envelope) error {
|
||||
topic := event.ToString()
|
||||
b.logger.Info("Unsubscribing topic", zap.String("topic", topic))
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
subs, ok := b.subscribers[topic]
|
||||
if !ok {
|
||||
b.logger.Debug("No subscribers for topic", zap.String("topic", topic))
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, ch := range subs {
|
||||
if ch == subChan {
|
||||
b.subscribers[topic] = append(subs[:i], subs[i+1:]...)
|
||||
close(ch)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
b.logger.Warn("No topic found", zap.String("topic", topic))
|
||||
return merrors.NoMessagingTopic(topic)
|
||||
}
|
||||
|
||||
func NewInProcessBroker(logger mlogger.Logger, bufferSize int) (*MessageBroker, error) {
|
||||
if bufferSize < 1 {
|
||||
return nil, merrors.InvalidArgument(fmt.Sprintf("Invelid buffer size %d. It must be greater than 1", bufferSize))
|
||||
}
|
||||
logger.Info("Created in-process logger", zap.Int("buffer_size", bufferSize))
|
||||
return &MessageBroker{
|
||||
logger: logger.Named("in_process"),
|
||||
subscribers: make(map[string][]chan me.Envelope),
|
||||
bufferSize: bufferSize,
|
||||
}, nil
|
||||
}
|
||||
5
api/pkg/messaging/internal/inprocess/config/config.go
Normal file
5
api/pkg/messaging/internal/inprocess/config/config.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package inprocess
|
||||
|
||||
type MessagingConfig struct {
|
||||
BufferSize int `mapstructure:"buffer_size" yaml:"buffer_size"`
|
||||
}
|
||||
Reference in New Issue
Block a user