edge/pkg/bus/memory/event_dispatcher.go

156 lines
2.5 KiB
Go
Raw Permalink Normal View History

2023-02-09 12:16:36 +01:00
package memory
import (
"context"
2023-02-09 12:16:36 +01:00
"sync"
"forge.cadoles.com/arcad/edge/pkg/bus"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
2023-02-09 12:16:36 +01:00
)
type eventDispatcherSet struct {
mutex sync.Mutex
items map[*eventDispatcher]struct{}
}
func (s *eventDispatcherSet) Add(d *eventDispatcher) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.items[d] = struct{}{}
}
func (s *eventDispatcherSet) Remove(d *eventDispatcher) {
s.mutex.Lock()
defer s.mutex.Unlock()
d.close()
delete(s.items, d)
}
2023-11-28 16:35:49 +01:00
func (s *eventDispatcherSet) RemoveByOutChannel(out <-chan bus.Envelope) {
2023-02-09 12:16:36 +01:00
s.mutex.Lock()
defer s.mutex.Unlock()
for d := range s.items {
if d.IsOut(out) {
d.close()
2023-02-09 12:16:36 +01:00
delete(s.items, d)
}
}
}
2023-11-28 16:35:49 +01:00
func (s *eventDispatcherSet) Range(fn func(d *eventDispatcher)) {
2023-02-09 12:16:36 +01:00
s.mutex.Lock()
defer s.mutex.Unlock()
for d := range s.items {
2023-11-28 16:35:49 +01:00
if d.Closed() {
s.Remove(d)
continue
}
2023-02-09 12:16:36 +01:00
2023-11-28 16:35:49 +01:00
fn(d)
}
2023-02-09 12:16:36 +01:00
}
func newEventDispatcherSet() *eventDispatcherSet {
return &eventDispatcherSet{
items: make(map[*eventDispatcher]struct{}),
}
}
type eventDispatcher struct {
2023-11-28 16:35:49 +01:00
in chan bus.Envelope
out chan bus.Envelope
2023-02-09 12:16:36 +01:00
mutex sync.RWMutex
closed bool
}
func (d *eventDispatcher) Closed() bool {
d.mutex.RLock()
defer d.mutex.RUnlock()
return d.closed
}
2023-02-09 12:16:36 +01:00
func (d *eventDispatcher) Close() {
d.mutex.Lock()
defer d.mutex.Unlock()
d.close()
}
func (d *eventDispatcher) close() {
if d.closed {
return
}
2023-02-09 12:16:36 +01:00
close(d.in)
d.closed = true
2023-02-09 12:16:36 +01:00
}
2023-11-28 16:35:49 +01:00
func (d *eventDispatcher) In(msg bus.Envelope) (err error) {
2023-02-09 12:16:36 +01:00
d.mutex.RLock()
defer d.mutex.RUnlock()
if d.closed {
return
}
d.in <- msg
return nil
}
2023-11-28 16:35:49 +01:00
func (d *eventDispatcher) Out() <-chan bus.Envelope {
2023-02-09 12:16:36 +01:00
return d.out
}
2023-11-28 16:35:49 +01:00
func (d *eventDispatcher) IsOut(out <-chan bus.Envelope) bool {
2023-02-09 12:16:36 +01:00
return d.out == out
}
func (d *eventDispatcher) Run(ctx context.Context) {
defer func() {
2023-11-28 16:35:49 +01:00
logger.Debug(ctx, "closing dispatcher, flushing out incoming messages")
2023-11-28 16:35:49 +01:00
close(d.out)
2023-11-28 16:35:49 +01:00
for range d.in {
// Flush all incoming messages
}
}()
2023-02-09 12:16:36 +01:00
for {
select {
2023-11-28 16:35:49 +01:00
case <-ctx.Done():
if err := ctx.Err(); !errors.Is(err, context.Canceled) {
logger.Error(
ctx,
"message subscription context canceled",
logger.CapturedE(errors.WithStack(err)),
)
}
return
2023-11-28 16:35:49 +01:00
case msg, ok := <-d.in:
if !ok {
return
}
2023-11-28 16:35:49 +01:00
d.out <- msg
}
2023-02-09 12:16:36 +01:00
}
}
func newEventDispatcher(bufferSize int64) *eventDispatcher {
return &eventDispatcher{
2023-11-28 16:35:49 +01:00
in: make(chan bus.Envelope, bufferSize),
out: make(chan bus.Envelope, bufferSize),
2023-02-09 12:16:36 +01:00
closed: false,
}
}