Skip to content

Commit 2671ff9

Browse files
evidolobcfergeau
andcommitted
Add events implementation
It allows us to have unified way to propagate state changes across an app Co-Authored-By: Christophe Fergeau <cfergeau@redhat.com> Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com>
1 parent 71b0f23 commit 2671ff9

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

pkg/events/emitter.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package events
2+
3+
import (
4+
"sync"
5+
)
6+
7+
type Event[T any] interface {
8+
AddListener(listener Notifiable[T])
9+
RemoveListener(listener Notifiable[T])
10+
Fire(data T)
11+
}
12+
13+
type Notifiable[T any] interface {
14+
Notify(event T)
15+
}
16+
17+
type event[T any] struct {
18+
listeners map[Notifiable[T]]Notifiable[T]
19+
eventMutex sync.Mutex
20+
}
21+
22+
func NewEvent[T any]() Event[T] {
23+
return &event[T]{
24+
listeners: make(map[Notifiable[T]]Notifiable[T]),
25+
}
26+
}
27+
28+
func (e *event[T]) AddListener(listener Notifiable[T]) {
29+
e.eventMutex.Lock()
30+
defer e.eventMutex.Unlock()
31+
e.listeners[listener] = listener
32+
}
33+
34+
func (e *event[T]) RemoveListener(listener Notifiable[T]) {
35+
e.eventMutex.Lock()
36+
defer e.eventMutex.Unlock()
37+
delete(e.listeners, listener)
38+
}
39+
40+
func (e *event[T]) Fire(event T) {
41+
e.eventMutex.Lock()
42+
defer e.eventMutex.Unlock()
43+
for _, listener := range e.listeners {
44+
go listener.Notify(event)
45+
}
46+
}

pkg/events/emitter_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package events
2+
3+
import (
4+
"sync"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
type TestEventData struct {
11+
Foo string
12+
}
13+
14+
type eventListener struct {
15+
notifyCb func(e TestEventData)
16+
}
17+
18+
func newEventListener(notifyCb func(e TestEventData)) *eventListener {
19+
return &eventListener{notifyCb: notifyCb}
20+
}
21+
22+
func (listener *eventListener) Notify(e TestEventData) {
23+
listener.notifyCb(e)
24+
}
25+
26+
func TestEmitter(t *testing.T) {
27+
var wg sync.WaitGroup
28+
wg.Add(1)
29+
var data string
30+
31+
event := NewEvent[TestEventData]()
32+
event.AddListener(newEventListener(func(e TestEventData) {
33+
data = e.Foo
34+
wg.Done()
35+
}))
36+
event.Fire(TestEventData{Foo: "bar"})
37+
38+
wg.Wait()
39+
40+
assert.Equal(t, "bar", data)
41+
}

0 commit comments

Comments
 (0)