discovery: prevent double-close panic; fix IPv6 URLs & expiration guard
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9f7b1a34065de77f4a8982b0f5feebc86a6a6964
This commit is contained in:
parent
5fc3b2883b
commit
0f62641d23
1 changed files with 8 additions and 3 deletions
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ type Discovery struct {
|
||||||
discovered map[string]*discoveredPeer
|
discovered map[string]*discoveredPeer
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
|
stopOnce sync.Once
|
||||||
waitGroup sync.WaitGroup
|
waitGroup sync.WaitGroup
|
||||||
onAddUpstream func(url string, priority int)
|
onAddUpstream func(url string, priority int)
|
||||||
onRemoveUpstream func(url string)
|
onRemoveUpstream func(url string)
|
||||||
|
|
@ -71,6 +73,7 @@ func (d *Discovery) Start(ctx context.Context) error {
|
||||||
|
|
||||||
if err := d.resolver.Browse(ctx, d.cfg.ServiceName, d.cfg.Domain, entries); err != nil {
|
if err := d.resolver.Browse(ctx, d.cfg.ServiceName, d.cfg.Domain, entries); err != nil {
|
||||||
close(entries)
|
close(entries)
|
||||||
|
d.stopOnce.Do(func() { close(d.stopCh) })
|
||||||
d.waitGroup.Wait()
|
d.waitGroup.Wait()
|
||||||
return fmt.Errorf("browse services: %w", err)
|
return fmt.Errorf("browse services: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +88,7 @@ func (d *Discovery) Start(ctx context.Context) error {
|
||||||
|
|
||||||
// Stops the discovery process.
|
// Stops the discovery process.
|
||||||
func (d *Discovery) Stop() {
|
func (d *Discovery) Stop() {
|
||||||
close(d.stopCh)
|
d.stopOnce.Do(func() { close(d.stopCh) })
|
||||||
d.waitGroup.Wait()
|
d.waitGroup.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,8 +125,7 @@ func (d *Discovery) handleEntry(_ context.Context, entry *zeroconf.ServiceEntry)
|
||||||
addr = entry.AddrIPv6[0].String()
|
addr = entry.AddrIPv6[0].String()
|
||||||
}
|
}
|
||||||
|
|
||||||
port := entry.Port
|
url := "http://" + net.JoinHostPort(addr, fmt.Sprintf("%d", entry.Port))
|
||||||
url := fmt.Sprintf("http://%s:%d", addr, port)
|
|
||||||
key := fmt.Sprintf("%s@%s", entry.Instance, entry.HostName)
|
key := fmt.Sprintf("%s@%s", entry.Instance, entry.HostName)
|
||||||
|
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
|
|
@ -184,6 +186,9 @@ func (d *Discovery) cleanupPeers() {
|
||||||
// TTL is the discovery response time; peers should re-announce periodically.
|
// TTL is the discovery response time; peers should re-announce periodically.
|
||||||
// Use 3x TTL as the expiration window.
|
// Use 3x TTL as the expiration window.
|
||||||
expiration := d.cfg.DiscoveryTime.Duration * 3
|
expiration := d.cfg.DiscoveryTime.Duration * 3
|
||||||
|
if expiration == 0 {
|
||||||
|
expiration = time.Second
|
||||||
|
}
|
||||||
|
|
||||||
for key, peer := range d.discovered {
|
for key, peer := range d.discovered {
|
||||||
if now.Sub(peer.lastSeen) > expiration {
|
if now.Sub(peer.lastSeen) > expiration {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue