package serverevents import ( "slices" "sync" "github.com/google/uuid" ) var emitter *EventEmitter type Subscription struct { id string eventType string todo func(Event) emitter *EventEmitter } func (sub Subscription) Unsubscribe() { if len(sub.eventType) < 1 { emitter.onAllSubscribers = slices.DeleteFunc(emitter.onAllSubscribers, func(existSub Subscription) bool { return existSub.id == sub.id }) return } eventSubscribers := emitter.subscribers[sub.eventType] if eventSubscribers == nil || len(eventSubscribers) < 1 { return } emitter.subscribers[sub.eventType] = slices.DeleteFunc(emitter.subscribers[sub.eventType], func(existSub Subscription) bool { return existSub.id == sub.id }) } type Event struct { Type string `json:"type"` Data any `json:"data"` IsBackendOnly bool `json:"-"` } type EventEmitter struct { subscribers map[string][]Subscription onAllSubscribers []Subscription mu sync.RWMutex } func GetEventEmitter() *EventEmitter { if emitter == nil { emitter = &EventEmitter{ subscribers: make(map[string][]Subscription), onAllSubscribers: make([]Subscription, 0), } } return emitter } func (em *EventEmitter) On(eventType string, do func(Event)) Subscription { em.mu.Lock() defer em.mu.Unlock() if em.subscribers[eventType] == nil { em.subscribers[eventType] = make([]Subscription, 0) } sub := Subscription{ id: uuid.NewString(), eventType: eventType, todo: do, emitter: em, } em.subscribers[eventType] = append(em.subscribers[eventType], sub) return sub } func (em *EventEmitter) OnAll(do func(Event)) Subscription { em.mu.Lock() defer em.mu.Unlock() sub := Subscription{ id: uuid.NewString(), todo: do, emitter: em, } em.onAllSubscribers = append(em.onAllSubscribers, sub) return sub } func (em *EventEmitter) Emit(event Event) { executeSubscribers(em.onAllSubscribers, event) eventSubscribers := em.subscribers[event.Type] if eventSubscribers != nil { executeSubscribers(eventSubscribers, event) } } func executeSubscribers(toDos []Subscription, event Event) { for _, sub := range toDos { sub.todo(event) } }