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 }