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) } }