network: don't attempt to connect to the same node twice

We can have multiple copies of the same address in the pool and we should only
proceed to connect once per attempt.
This commit is contained in:
Roman Khimov 2021-03-26 12:26:45 +03:00
parent 46a59e904a
commit 9d6439bbe6

View file

@ -37,6 +37,7 @@ type DefaultDiscovery struct {
connectedAddrs map[string]bool connectedAddrs map[string]bool
goodAddrs map[string]bool goodAddrs map[string]bool
unconnectedAddrs map[string]int unconnectedAddrs map[string]int
attempted map[string]bool
isDead bool isDead bool
requestCh chan int requestCh chan int
pool chan string pool chan string
@ -52,6 +53,7 @@ func NewDefaultDiscovery(addrs []string, dt time.Duration, ts Transporter) *Defa
connectedAddrs: make(map[string]bool), connectedAddrs: make(map[string]bool),
goodAddrs: make(map[string]bool), goodAddrs: make(map[string]bool),
unconnectedAddrs: make(map[string]int), unconnectedAddrs: make(map[string]int),
attempted: make(map[string]bool),
requestCh: make(chan int), requestCh: make(chan int),
pool: make(chan string, maxPoolSize), pool: make(chan string, maxPoolSize),
} }
@ -174,7 +176,11 @@ func (d *DefaultDiscovery) RegisterConnectedAddr(addr string) {
} }
func (d *DefaultDiscovery) tryAddress(addr string) { func (d *DefaultDiscovery) tryAddress(addr string) {
if err := d.transport.Dial(addr, d.dialTimeout); err != nil { err := d.transport.Dial(addr, d.dialTimeout)
d.lock.Lock()
delete(d.attempted, addr)
d.lock.Unlock()
if err != nil {
d.RegisterBadAddr(addr) d.RegisterBadAddr(addr)
d.RequestRemote(1) d.RequestRemote(1)
} }
@ -210,14 +216,14 @@ func (d *DefaultDiscovery) run() {
requested = r requested = r
} }
case addr := <-d.pool: case addr := <-d.pool:
d.lock.RLock()
addrIsConnected := d.connectedAddrs[addr]
d.lock.RUnlock()
updatePoolCountMetric(d.PoolCount()) updatePoolCountMetric(d.PoolCount())
if !addrIsConnected { d.lock.Lock()
if !d.connectedAddrs[addr] && !d.attempted[addr] {
d.attempted[addr] = true
go d.tryAddress(addr) go d.tryAddress(addr)
requested-- requested--
} }
d.lock.Unlock()
default: // Empty pool default: // Empty pool
d.lock.Lock() d.lock.Lock()
for _, addr := range d.seeds { for _, addr := range d.seeds {