server_events/v2/emitter.go

90 lines
2.2 KiB
Go

package serverevents
import (
di "git.apihub24.de/admin/generic-di"
"github.com/google/uuid"
"slices"
"sync"
)
func init() {
di.Injectable(newEventEmitter)
}
type IEventEmitter interface {
On(eventType string, do func(Event)) Subscription
OnAll(do func(Event)) Subscription
Emit(event Event)
Unsubscribe(Subscription)
}
type eventEmitter struct {
subscribers map[string][]Subscription
onAllSubscribers []Subscription
mu sync.RWMutex
}
func newEventEmitter() IEventEmitter {
return &eventEmitter{}
}
func (emitter *eventEmitter) On(eventType string, do func(Event)) Subscription {
emitter.mu.Lock()
defer emitter.mu.Unlock()
if emitter.subscribers[eventType] == nil {
emitter.subscribers[eventType] = make([]Subscription, 0)
}
sub := Subscription{
id: uuid.NewString(),
eventType: eventType,
todo: do,
emitter: emitter,
}
emitter.subscribers[eventType] = append(emitter.subscribers[eventType], sub)
return sub
}
func (emitter *eventEmitter) OnAll(do func(Event)) Subscription {
emitter.mu.Lock()
defer emitter.mu.Unlock()
sub := Subscription{
id: uuid.NewString(),
todo: do,
emitter: emitter,
}
emitter.onAllSubscribers = append(emitter.onAllSubscribers, sub)
return sub
}
func (emitter *eventEmitter) Emit(event Event) {
emitter.executeSubscribers(emitter.onAllSubscribers, event)
eventSubscribers := emitter.subscribers[event.Type]
if eventSubscribers != nil {
emitter.executeSubscribers(eventSubscribers, event)
}
}
func (emitter *eventEmitter) Unsubscribe(subscription Subscription) {
if len(subscription.eventType) < 1 {
emitter.onAllSubscribers = slices.DeleteFunc(emitter.onAllSubscribers, func(existSub Subscription) bool {
return existSub.id == subscription.id
})
return
}
eventSubscribers := emitter.subscribers[subscription.eventType]
if eventSubscribers == nil || len(eventSubscribers) < 1 {
return
}
emitter.subscribers[subscription.eventType] = slices.DeleteFunc(emitter.subscribers[subscription.eventType], func(existSub Subscription) bool {
return existSub.id == subscription.id
})
}
func (emitter *eventEmitter) executeSubscribers(toDos []Subscription, event Event) {
for _, sub := range toDos {
sub.todo(event)
}
}