p2p: add a dialer cooldown to prevent reattempting failures

This commit is contained in:
Péter Szilágyi 2015-04-29 18:42:43 +03:00
parent 3b58f5a2c5
commit 5dde733d0c
2 changed files with 25 additions and 3 deletions

View file

@ -73,6 +73,7 @@ const (
DiscSelf
DiscReadTimeout
DiscSubprotocolError
DiscFailureCooldown
)
var discReasonToString = [...]string{
@ -89,6 +90,7 @@ var discReasonToString = [...]string{
DiscSelf: "Connected to self",
DiscReadTimeout: "Read timeout",
DiscSubprotocolError: "Subprotocol error",
DiscFailureCooldown: "Failure cooldown",
}
func (d DiscReason) String() string {

View file

@ -21,6 +21,7 @@ const (
defaultDialTimeout = 10 * time.Second
refreshPeersInterval = 30 * time.Second
trustedPeerCheckInterval = 15 * time.Second
dialFailureCooldown = 30 * time.Second
// This is the maximum number of inbound connection
// that are allowed to linger between 'accepted' and
@ -100,9 +101,11 @@ type Server struct {
ourHandshake *protoHandshake
lock sync.RWMutex // protects running and peers
lock sync.RWMutex // protects running and peers
running bool
peers map[discover.NodeID]*Peer
peers map[discover.NodeID]*Peer // Currently active peer pool
fails map[discover.NodeID]bool // List of recently failed connections
trusts map[discover.NodeID]*discover.Node // Map of currently trusted remote nodes
trustDial chan *discover.Node // Dial request channel reserved for the trusted nodes
@ -201,6 +204,7 @@ func (srv *Server) Start() (err error) {
}
srv.quit = make(chan struct{})
srv.peers = make(map[discover.NodeID]*Peer)
srv.fails = make(map[discover.NodeID]bool)
// Create the current trust map, and the associated dialing channel
srv.trusts = make(map[discover.NodeID]*discover.Node)
@ -456,7 +460,20 @@ func (srv *Server) dialNode(dest *discover.Node) {
// dialNode, so we need to count it down again. startPeer also
// does that when an error occurs.
srv.peerWG.Done()
glog.V(logger.Detail).Infof("dial error: %v", err)
// Mark the dialing as failed so prevent too fast redials, and set a
// timer for re-allowing dialing
srv.lock.Lock()
srv.fails[dest.ID] = true
srv.lock.Unlock()
go func() {
glog.V(logger.Detail).Infof("Dialing %v failed: %v. Locked until %v\n", dest, err, time.Now().Add(dialFailureCooldown))
<-time.After(dialFailureCooldown)
srv.lock.Lock()
delete(srv.fails, dest.ID)
srv.lock.Unlock()
}()
return
}
srv.startPeer(conn, dest)
@ -546,6 +563,9 @@ func (srv *Server) checkPeer(id discover.NodeID) (bool, DiscReason) {
case id == srv.ntab.Self().ID:
return false, DiscSelf
case srv.fails[id]:
return false, DiscFailureCooldown
default:
return true, 0
}