Files
silo-server/internal/nodepool/proxy_pool.go
T

56 lines
1.1 KiB
Go

package nodepool
import (
"sync"
"sync/atomic"
)
// ProxyPool manages proxy nodes with round-robin selection.
// Thread-safe for concurrent use.
type ProxyPool struct {
nodes []*Node
mu sync.RWMutex
nextIdx atomic.Uint64
}
// NewProxyPool creates an empty proxy pool.
func NewProxyPool() *ProxyPool {
return &ProxyPool{}
}
// SetNodes replaces the node list. Called on startup and when admin changes nodes.
func (p *ProxyPool) SetNodes(nodes []*Node) {
p.mu.Lock()
defer p.mu.Unlock()
p.nodes = nodes
}
// Pick returns a healthy node using round-robin selection.
// Returns nil if no healthy nodes are available.
func (p *ProxyPool) Pick() *Node {
p.mu.RLock()
defer p.mu.RUnlock()
n := len(p.nodes)
if n == 0 {
return nil
}
start := int(p.nextIdx.Add(1) - 1)
for i := range n {
node := p.nodes[(start+i)%n]
if node.Healthy && node.Enabled {
return node
}
}
return nil
}
// Nodes returns a copy of the current node list.
func (p *ProxyPool) Nodes() []*Node {
p.mu.RLock()
defer p.mu.RUnlock()
cp := make([]*Node, len(p.nodes))
copy(cp, p.nodes)
return cp
}