@@ -223,7 +223,10 @@ proc loadFromStorage(pm: PeerManager) {.gcsafe.} =
223223 pm.switch.peerStore[ConnectionBook ][peerId] = NotConnected
224224 # Reset connectedness state
225225 pm.switch.peerStore[DisconnectBook ][peerId] = remotePeerInfo.disconnectTime
226- pm.switch.peerStore[SourceBook ][peerId] = remotePeerInfo.origin
226+ # Mark as Cache so it is distinguishable from live-discovered peers. If the
227+ # same peer is later rediscovered, addPeer overrides this with the live
228+ # origin, and reconnect backoff no longer applies to it.
229+ pm.switch.peerStore[SourceBook ][peerId] = Cache
227230
228231 if remotePeerInfo.enr.isSome ():
229232 pm.switch.peerStore[ENRBook ][peerId] = remotePeerInfo.enr.get ()
@@ -695,21 +698,28 @@ proc reconnectPeers*(
695698
696699 info " Reconnecting peers" , proto = proto
697700
698- # Proto is not persisted, we need to iterate over all peers.
699- for peerInfo in pm.switch.peerStore. peers ( protocolMatcher (proto)):
700- # Check that the peer can be connected
701- if peerInfo.connectedness == CannotConnect :
702- error " Not reconnecting to unreachable or non-existing peer " ,
703- peerId = peerInfo.peerId
704- continue
701+ # Only reconnect peers that come from persistent storage (Cache). Freshly
702+ # discovered peers must not be delayed by the reconnect backoff: they are
703+ # connected right away by the relay connectivity loop. Rediscovered peers get
704+ # their origin overridden by addPeer, so they naturally drop out of this set.
705+ let peersToReconnect = pm.switch.peerStore. peers ( protocolMatcher (proto)). filterIt (
706+ it.origin == Cache and it.connectedness != CannotConnect
707+ )
705708
706- if backoffTime > ZeroDuration :
707- info " Backing off before reconnect" ,
708- peerId = peerInfo.peerId, backoffTime = backoffTime
709- # We disconnected recently and still need to wait for a backoff period before connecting
710- await sleepAsync (backoffTime)
709+ if peersToReconnect.len == 0 :
710+ return
711711
712- await pm.connectToNodes (@ [peerInfo])
712+ # We disconnected recently and still need to wait a backoff period before
713+ # reconnecting. The wait is shared across all peers rather than applied once
714+ # per peer, so reconnection can't stall behind a slow/unreachable peer and
715+ # keep the node from taking on freshly discovered ones.
716+ if backoffTime > ZeroDuration :
717+ info " Backing off before reconnect" , backoffTime = backoffTime
718+ await sleepAsync (backoffTime)
719+
720+ # Dial all reconnectable peers in parallel; a single slow dial must not delay
721+ # the rest.
722+ await allFutures (peersToReconnect.mapIt (pm.connectToNodes (@ [it])))
713723
714724proc getNumStreams * (pm: PeerManager , protocol: string ): (int , int ) =
715725 var
0 commit comments