Remove go routines for mdns watcher and cache registry (#919)

This commit is contained in:
Asim Aslam
2019-11-06 15:49:40 +00:00
committed by GitHub
parent b84134581c
commit 254045e9f3
3 changed files with 128 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/google/uuid"
"github.com/micro/mdns"
)
@@ -37,6 +38,14 @@ type mdnsRegistry struct {
sync.Mutex
services map[string][]*mdnsEntry
mtx sync.RWMutex
// watchers
watchers map[string]*mdnsWatcher
// listener
listener chan *mdns.ServiceEntry
}
func newRegistry(opts ...Option) Registry {
@@ -61,6 +70,7 @@ func newRegistry(opts ...Option) Registry {
opts: options,
domain: domain,
services: make(map[string][]*mdnsEntry),
watchers: make(map[string]*mdnsWatcher),
}
}
@@ -346,15 +356,88 @@ func (m *mdnsRegistry) Watch(opts ...WatchOption) (Watcher, error) {
}
md := &mdnsWatcher{
wo: wo,
ch: make(chan *mdns.ServiceEntry, 32),
exit: make(chan struct{}),
domain: m.domain,
id: uuid.New().String(),
wo: wo,
ch: make(chan *mdns.ServiceEntry, 32),
exit: make(chan struct{}),
domain: m.domain,
registry: m,
}
m.mtx.Lock()
defer m.mtx.Unlock()
// save the watcher
m.watchers[md.id] = md
// check of the listener exists
if m.listener != nil {
return md, nil
}
// start the listener
go func() {
if err := mdns.Listen(md.ch, md.exit); err != nil {
md.Stop()
// go to infinity
for {
m.mtx.Lock()
// just return if there are no watchers
if len(m.watchers) == 0 {
m.listener = nil
m.mtx.Unlock()
return
}
// check existing listener
if m.listener != nil {
m.mtx.Unlock()
return
}
// reset the listener
exit := make(chan struct{})
ch := make(chan *mdns.ServiceEntry, 32)
m.listener = ch
m.mtx.Unlock()
// send messages to the watchers
go func() {
send := func(w *mdnsWatcher, e *mdns.ServiceEntry) {
select {
case w.ch <- e:
default:
}
}
for {
select {
case <-exit:
return
case e, ok := <-ch:
if !ok {
return
}
m.mtx.RLock()
// send service entry to all watchers
for _, w := range m.watchers {
send(w, e)
}
m.mtx.RUnlock()
}
}
}()
// start listening, blocking call
mdns.Listen(ch, exit)
// mdns.Listen has unblocked
// kill the saved listener
m.mtx.Lock()
m.listener = nil
close(ch)
m.mtx.Unlock()
}
}()