81 lines
1.4 KiB
Go
81 lines
1.4 KiB
Go
|
package sati
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/mitchellh/mapstructure"
|
||
|
)
|
||
|
|
||
|
type EventBus struct {
|
||
|
mu *sync.Mutex
|
||
|
idCounter uint32
|
||
|
handlers map[string]map[uint32]func(data any)
|
||
|
eventTypes map[string]any
|
||
|
}
|
||
|
|
||
|
type EventHandler struct {
|
||
|
id uint32
|
||
|
type_ string
|
||
|
bus *EventBus
|
||
|
}
|
||
|
|
||
|
func (e *EventHandler) Off() {
|
||
|
e.bus.mu.Lock()
|
||
|
defer e.bus.mu.Unlock()
|
||
|
|
||
|
delete(e.bus.handlers[e.type_], e.id)
|
||
|
}
|
||
|
|
||
|
func (e *EventBus) On(event string, handler func(data any)) (*EventHandler, error) {
|
||
|
e.mu.Lock()
|
||
|
defer e.mu.Unlock()
|
||
|
|
||
|
if _, ok := e.eventTypes[event]; !ok {
|
||
|
return nil, fmt.Errorf("bad event type")
|
||
|
}
|
||
|
|
||
|
e.idCounter++
|
||
|
e.handlers[event][e.idCounter] = handler
|
||
|
return &EventHandler{
|
||
|
id: e.idCounter,
|
||
|
type_: event,
|
||
|
bus: e,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (e *EventBus) dispatch(event string, data any) error {
|
||
|
e.mu.Lock()
|
||
|
defer e.mu.Unlock()
|
||
|
|
||
|
formattedData, ok := e.eventTypes[event]
|
||
|
if !ok {
|
||
|
return fmt.Errorf("bad event type")
|
||
|
}
|
||
|
|
||
|
if err := mapstructure.Decode(data, &formattedData); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
for _, handler := range e.handlers[event] {
|
||
|
handler(formattedData)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// eventTypes values must be structs, not pointers
|
||
|
func newEventBus(eventTypes map[string]any) *EventBus {
|
||
|
e := &EventBus{
|
||
|
mu: &sync.Mutex{},
|
||
|
handlers: make(map[string]map[uint32]func(data any)),
|
||
|
eventTypes: eventTypes,
|
||
|
}
|
||
|
|
||
|
for event := range eventTypes {
|
||
|
e.handlers[event] = make(map[uint32]func(data any))
|
||
|
}
|
||
|
|
||
|
return e
|
||
|
}
|