code: func (cm *ConnManager) handleFailedConn(c *ConnReq) {
  	if atomic.LoadInt32(&cm.stop) != 0 {
  		return
  	}
  	if c.Permanent {
  		c.retryCount++
  		d := time.Duration(c.retryCount) * cm.cfg.RetryDuration
  		if d > maxRetryDuration {
  			d = maxRetryDuration
  		}
  		log.Debugf("Retrying connection to %v in %v", c, d)
  		time.AfterFunc(d, func() {
  			cm.Connect(c)
  		})
  	} else if cm.cfg.GetNewAddress != nil {
  		cm.failedAttempts++
  		if cm.failedAttempts >= maxFailedAttempts {
  			log.Debugf("Max failed connection attempts reached: [%d] "+
  				"-- retrying connection in: %v", maxFailedAttempts,
  				cm.cfg.RetryDuration)
  			time.AfterFunc(cm.cfg.RetryDuration, func() {
  				cm.NewConnReq()
  			})
  		} else {
  			go cm.NewConnReq()
  		}
  	}
  }
docs: // handleFailedConn handles a connection failed due to a disconnect or any
  // other failure. If permanent, it retries the connection after the configured
  // retry duration. Otherwise, if required, it makes a new connection request.
  // After maxFailedConnectionAttempts new connections will be retried after the
  // configured retry duration.