|
|
|
@ -25,11 +25,11 @@ import (
@@ -25,11 +25,11 @@ import (
|
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"log" |
|
|
|
|
"sync" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/nats-io/nats" |
|
|
|
|
|
|
|
|
|
"github.com/strukturag/spreed-webrtc/go/buffercache" |
|
|
|
|
"github.com/strukturag/spreed-webrtc/go/natsconnection" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -45,11 +45,15 @@ const (
@@ -45,11 +45,15 @@ const (
|
|
|
|
|
|
|
|
|
|
// A BusManager provides the API to interact with a bus.
|
|
|
|
|
type BusManager interface { |
|
|
|
|
ChannellingAPIConsumer |
|
|
|
|
Start() |
|
|
|
|
Publish(subject string, v interface{}) error |
|
|
|
|
Request(subject string, v interface{}, vPtr interface{}, timeout time.Duration) error |
|
|
|
|
Trigger(name, from, payload string, data interface{}, pipeline *Pipeline) error |
|
|
|
|
Subscribe(subject string, cb nats.Handler) (*nats.Subscription, error) |
|
|
|
|
BindRecvChan(subject string, channel interface{}) (*nats.Subscription, error) |
|
|
|
|
BindSendChan(subject string, channel interface{}) error |
|
|
|
|
PrefixSubject(string) string |
|
|
|
|
CreateSink(string) Sink |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -69,32 +73,29 @@ func BusSubjectTrigger(prefix, suffix string) string {
@@ -69,32 +73,29 @@ func BusSubjectTrigger(prefix, suffix string) string {
|
|
|
|
|
return fmt.Sprintf("%s.%s", prefix, suffix) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type busManager struct { |
|
|
|
|
BusManager |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NewBusManager creates and initializes a new BusMager with the
|
|
|
|
|
// provided flags for NATS support. It is intended to connect the
|
|
|
|
|
// backend bus with a easy to use API to send and receive bus data.
|
|
|
|
|
func NewBusManager(id string, useNats bool, subjectPrefix string) BusManager { |
|
|
|
|
func NewBusManager(apiConsumer ChannellingAPIConsumer, id string, useNats bool, subjectPrefix string) BusManager { |
|
|
|
|
var b BusManager |
|
|
|
|
var err error |
|
|
|
|
if useNats { |
|
|
|
|
b, err = newNatsBus(id, subjectPrefix) |
|
|
|
|
b, err = newNatsBus(apiConsumer, id, subjectPrefix) |
|
|
|
|
if err == nil { |
|
|
|
|
log.Println("NATS bus connected") |
|
|
|
|
} else { |
|
|
|
|
log.Println("Error connecting NATS bus", err) |
|
|
|
|
b = &noopBus{id} |
|
|
|
|
b = &noopBus{apiConsumer, id} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
b = &noopBus{id} |
|
|
|
|
b = &noopBus{apiConsumer, id} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return &busManager{b} |
|
|
|
|
return b |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type noopBus struct { |
|
|
|
|
ChannellingAPIConsumer |
|
|
|
|
id string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -114,6 +115,18 @@ func (bus *noopBus) Trigger(name, from, payload string, data interface{}, pipeli
@@ -114,6 +115,18 @@ func (bus *noopBus) Trigger(name, from, payload string, data interface{}, pipeli
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *noopBus) PrefixSubject(subject string) string { |
|
|
|
|
return subject |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *noopBus) BindRecvChan(subject string, channel interface{}) (*nats.Subscription, error) { |
|
|
|
|
return nil, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *noopBus) BindSendChan(subject string, channel interface{}) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *noopBus) Subscribe(subject string, cb nats.Handler) (*nats.Subscription, error) { |
|
|
|
|
return nil, nil |
|
|
|
|
} |
|
|
|
@ -123,13 +136,14 @@ func (bus *noopBus) CreateSink(id string) Sink {
@@ -123,13 +136,14 @@ func (bus *noopBus) CreateSink(id string) Sink {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type natsBus struct { |
|
|
|
|
ChannellingAPIConsumer |
|
|
|
|
id string |
|
|
|
|
prefix string |
|
|
|
|
ec *natsconnection.EncodedConnection |
|
|
|
|
triggerQueue chan *busQueueEntry |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func newNatsBus(id, prefix string) (*natsBus, error) { |
|
|
|
|
func newNatsBus(apiConsumer ChannellingAPIConsumer, id, prefix string) (*natsBus, error) { |
|
|
|
|
ec, err := natsconnection.EstablishJSONEncodedConnection(nil) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
@ -139,13 +153,13 @@ func newNatsBus(id, prefix string) (*natsBus, error) {
@@ -139,13 +153,13 @@ func newNatsBus(id, prefix string) (*natsBus, error) {
|
|
|
|
|
} |
|
|
|
|
// Create buffered channel for outbound NATS data.
|
|
|
|
|
triggerQueue := make(chan *busQueueEntry, 50) |
|
|
|
|
// Start go routine to process outbount NATS publishing.
|
|
|
|
|
go chPublish(ec, triggerQueue) |
|
|
|
|
|
|
|
|
|
return &natsBus{id, prefix, ec, triggerQueue}, nil |
|
|
|
|
return &natsBus{apiConsumer, id, prefix, ec, triggerQueue}, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) Start() { |
|
|
|
|
// Start go routine to process outbount NATS publishing.
|
|
|
|
|
go chPublish(bus.ec, bus.triggerQueue) |
|
|
|
|
bus.Trigger(BusManagerStartup, bus.id, "", nil, nil) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -180,12 +194,25 @@ func (bus *natsBus) Trigger(name, from, payload string, data interface{}, pipeli
@@ -180,12 +194,25 @@ func (bus *natsBus) Trigger(name, from, payload string, data interface{}, pipeli
|
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) PrefixSubject(sub string) string { |
|
|
|
|
return fmt.Sprintf("%s.%s", bus.prefix, sub) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) Subscribe(subject string, cb nats.Handler) (*nats.Subscription, error) { |
|
|
|
|
return bus.ec.Subscribe(subject, cb) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) CreateSink(id string) Sink { |
|
|
|
|
return &natsSink{} |
|
|
|
|
func (bus *natsBus) BindRecvChan(subject string, channel interface{}) (*nats.Subscription, error) { |
|
|
|
|
return bus.ec.BindRecvChan(subject, channel) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) BindSendChan(subject string, channel interface{}) error { |
|
|
|
|
return bus.ec.BindSendChan(subject, channel) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bus *natsBus) CreateSink(id string) (sink Sink) { |
|
|
|
|
sink = newNatsSink(bus, id) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type busQueueEntry struct { |
|
|
|
@ -204,17 +231,76 @@ func chPublish(ec *natsconnection.EncodedConnection, channel chan (*busQueueEntr
@@ -204,17 +231,76 @@ func chPublish(ec *natsconnection.EncodedConnection, channel chan (*busQueueEntr
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type natsSink struct { |
|
|
|
|
sync.RWMutex |
|
|
|
|
id string |
|
|
|
|
bm BusManager |
|
|
|
|
closed bool |
|
|
|
|
SubjectOut string |
|
|
|
|
SubjectIn string |
|
|
|
|
sub *nats.Subscription |
|
|
|
|
sendQueue chan *DataOutgoing |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) Write(data interface{}) { |
|
|
|
|
func newNatsSink(bm BusManager, id string) *natsSink { |
|
|
|
|
sink := &natsSink{ |
|
|
|
|
id: id, |
|
|
|
|
bm: bm, |
|
|
|
|
SubjectOut: bm.PrefixSubject(fmt.Sprintf("sink.%s.out", id)), |
|
|
|
|
SubjectIn: bm.PrefixSubject(fmt.Sprintf("sink.%s.in", id)), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sink.sendQueue = make(chan *DataOutgoing, 100) |
|
|
|
|
bm.BindSendChan(sink.SubjectOut, sink.sendQueue) |
|
|
|
|
|
|
|
|
|
return sink |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) Send(b buffercache.Buffer) { |
|
|
|
|
func (sink *natsSink) Write(outgoing *DataOutgoing) (err error) { |
|
|
|
|
if sink.Enabled() { |
|
|
|
|
log.Println("Sending via NATS sink", sink.SubjectOut, outgoing) |
|
|
|
|
sink.sendQueue <- outgoing |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) Enabled() bool { |
|
|
|
|
return false |
|
|
|
|
sink.RLock() |
|
|
|
|
defer sink.RUnlock() |
|
|
|
|
return sink.closed == false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) Close() { |
|
|
|
|
sink.Lock() |
|
|
|
|
defer sink.Unlock() |
|
|
|
|
if sink.sub != nil { |
|
|
|
|
err := sink.sub.Unsubscribe() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Println("Failed to unsubscribe NATS sink", err) |
|
|
|
|
} else { |
|
|
|
|
sink.sub = nil |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
sink.closed = true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) Export() *DataSink { |
|
|
|
|
return &DataSink{ |
|
|
|
|
SubjectOut: sink.SubjectOut, |
|
|
|
|
SubjectIn: sink.SubjectIn, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sink *natsSink) BindRecvChan(channel interface{}) (*nats.Subscription, error) { |
|
|
|
|
sink.Lock() |
|
|
|
|
defer sink.Unlock() |
|
|
|
|
if sink.sub != nil { |
|
|
|
|
sink.sub.Unsubscribe() |
|
|
|
|
sink.sub = nil |
|
|
|
|
} |
|
|
|
|
sub, err := sink.bm.BindRecvChan(sink.SubjectIn, channel) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
sink.sub = sub |
|
|
|
|
return sub, nil |
|
|
|
|
} |
|
|
|
|