This commit is contained in:
@@ -30,7 +30,9 @@ type Config struct {
|
||||
Seeds []string // other peers' mesh base URLs
|
||||
ClusterSecret string // HMAC key
|
||||
EnableDiscovery bool
|
||||
DiscoveryAddress string // "239.8.8.8:9898"
|
||||
DiscoveryAddress string // "239.8.8.8:9898"
|
||||
PeerTTL time.Duration // wie lange darf ein Peer inaktiv sein (Default siehe unten)
|
||||
PruneInterval time.Duration // wie oft wird gepruned
|
||||
}
|
||||
|
||||
type Peer struct {
|
||||
@@ -72,6 +74,78 @@ type Node struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// RemovePeer löscht einen Peer aus der Peer-Tabelle. Seeds werden standardmäßig nicht entfernt.
|
||||
func (n *Node) RemovePeer(url string) bool {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
if url == "" || url == n.self.URL {
|
||||
return false
|
||||
}
|
||||
// Seeds schützen
|
||||
if n.isSeed(url) {
|
||||
return false
|
||||
}
|
||||
if _, ok := n.peers[url]; ok {
|
||||
delete(n.peers, url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PruneNow entfernt alle Peers, deren LastSeen vor cutoff liegt (Seeds bleiben).
|
||||
func (n *Node) PruneNow(cutoff time.Time) int {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
removed := 0
|
||||
for url, p := range n.peers {
|
||||
if url == n.self.URL || n.isSeed(url) {
|
||||
continue
|
||||
}
|
||||
if p.LastSeen.IsZero() || p.LastSeen.Before(cutoff) {
|
||||
delete(n.peers, url)
|
||||
removed++
|
||||
}
|
||||
}
|
||||
return removed
|
||||
}
|
||||
|
||||
// StartPeerPruner startet den Hintergrundjob (stoppt automatisch bei n.stop).
|
||||
func (n *Node) StartPeerPruner() {
|
||||
go n.loopPrunePeers()
|
||||
}
|
||||
|
||||
func (n *Node) loopPrunePeers() {
|
||||
ttl := n.cfg.PeerTTL
|
||||
if ttl <= 0 {
|
||||
ttl = 2 * time.Minute
|
||||
}
|
||||
interval := n.cfg.PruneInterval
|
||||
if interval <= 0 {
|
||||
interval = 30 * time.Second
|
||||
}
|
||||
t := time.NewTicker(interval)
|
||||
defer t.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-n.stop:
|
||||
return
|
||||
case <-t.C:
|
||||
cutoff := time.Now().Add(-ttl)
|
||||
_ = n.PruneNow(cutoff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper: ist url ein Seed?
|
||||
func (n *Node) isSeed(url string) bool {
|
||||
for _, s := range n.cfg.Seeds {
|
||||
if strings.TrimSpace(s) == strings.TrimSpace(url) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func New(cfg Config, cbs Callbacks) (*Node, error) {
|
||||
if cfg.BindAddr == "" || cfg.AdvertURL == "" {
|
||||
return nil, errors.New("mesh: BindAddr and AdvertURL required")
|
||||
|
||||
Reference in New Issue
Block a user