events: don't explode when destroying a bus

Only attempt to close channels once, rather than per topic
they are subscribed to.
This commit is contained in:
Matthew Penner
2022-01-20 09:48:18 -07:00
parent 6d8c1d2225
commit 4ba5fe2866
4 changed files with 39 additions and 22 deletions

View File

@@ -3,6 +3,8 @@ package events
import (
"strings"
"sync"
"github.com/apex/log"
)
type Listener chan Event
@@ -31,8 +33,15 @@ func (b *Bus) Off(listener Listener, topics ...string) {
b.listenersMx.Lock()
defer b.listenersMx.Unlock()
var closed bool
for _, topic := range topics {
b.off(topic, listener)
ok := b.off(topic, listener)
if !closed && ok {
log.Debug("closing event channel!")
close(listener)
closed = true
}
}
}
@@ -116,11 +125,30 @@ func (b *Bus) Destroy() {
b.listenersMx.Lock()
defer b.listenersMx.Unlock()
// Track what listeners have already been closed. Because the same listener
// can be listening on multiple topics, we need a way to essentially
// "de-duplicate" all the listeners across all the topics.
var closed []Listener
for _, listeners := range b.listeners {
for _, listener := range listeners {
if contains(closed, listener) {
continue
}
close(listener)
closed = append(closed, listener)
}
}
b.listeners = make(map[string][]Listener)
}
func contains(closed []Listener, listener Listener) bool {
for _, c := range closed {
if c == listener {
return true
}
}
return false
}