eve

Tiny event emitter for Go
git clone git://git.lair.cx/eve
Log | Files | Refs | README | LICENSE

eve.go (910B)


      1 package eve
      2 
      3 import (
      4 	"context"
      5 	"sync"
      6 
      7 	"go.uber.org/multierr"
      8 )
      9 
     10 type (
     11 	eventFn[E any]  func(ctx context.Context, e E) error
     12 	eventMap[E any] map[uint64]eventFn[E]
     13 )
     14 
     15 type Event[E any] interface {
     16 	On(fn eventFn[E]) func()
     17 	Emit(ctx context.Context, event E) error
     18 }
     19 
     20 type event[E any] struct {
     21 	mu       sync.Mutex
     22 	acc      uint64
     23 	handlers map[uint64]eventFn[E]
     24 }
     25 
     26 func New[E any]() Event[E] {
     27 	return &event[E]{
     28 		handlers: make(eventMap[E]),
     29 	}
     30 }
     31 
     32 func (e *event[E]) On(fn eventFn[E]) func() {
     33 	e.mu.Lock()
     34 
     35 	id := e.acc
     36 	e.acc++
     37 
     38 	e.handlers[id] = fn
     39 
     40 	e.mu.Unlock()
     41 
     42 	canceled := false
     43 	return func() {
     44 		if canceled {
     45 			return
     46 		}
     47 
     48 		e.mu.Lock()
     49 		delete(e.handlers, id)
     50 		e.mu.Unlock()
     51 	}
     52 }
     53 
     54 func (e *event[E]) Emit(ctx context.Context, event E) error {
     55 	e.mu.Lock()
     56 	defer e.mu.Unlock()
     57 
     58 	var err error
     59 
     60 	for _, fn := range e.handlers {
     61 		multierr.Append(err, fn(ctx, event))
     62 	}
     63 
     64 	return err
     65 }