message: Refactor per-IP reconnection logic to be more fault tolerant
diff: @@ -119,6 +119,25 @@ impl Server {
  for addr in addrs {
  std::thread::sleep(backoff);
  + match self.try_connect_addr(addr, &op) {
  + Ok(result) => return Ok(result),
  + Err(e) => last_err = e,
  + };
  + }
  +
  + self.reconnects += 1;
  +
  + Err(last_err)
  + }
  +
  + // we split the specific connection function into its own
  + // function so we can use the try operator and have it more
  + // gracefully feed into `last_err` at the call site.
  + fn try_connect_addr(
  + &mut self,
  + addr: SocketAddr,
  + op: &str,
  + ) -> io::Result<(BufReader<TcpStream>, ServerInfo)> {
  let mut stream = TcpStream::connect(&addr)?;
  stream.write_all(op.as_bytes())?;
  @@ -130,27 +149,17 @@ impl Server {
  match parsed_op {
  ControlOp::Pong => {
  self.reconnects = 0;
  - return Ok((inbound, info));
  + Ok((inbound, info))
  }
  - ControlOp::Err(e) => {
  - last_err = Error::new(ErrorKind::ConnectionRefused, e);
  - }
  - ControlOp::Ping
  - | ControlOp::Msg(_)
  - | ControlOp::Info(_)
  - | ControlOp::Unknown(_) => {
  + ControlOp::Err(e) => Err(Error::new(ErrorKind::ConnectionRefused, e)),
  + ControlOp::Ping | ControlOp::Msg(_) | ControlOp::Info(_) | ControlOp::Unknown(_) => {
  eprintln!(
  "encountered unexpected control op during connection: {:?}",
  parsed_op
  );
  - last_err = Error::new(ErrorKind::ConnectionRefused, "Protocol Error");
  - }
  + Err(Error::new(ErrorKind::ConnectionRefused, "Protocol Error"))
  }
  }
  -
  - self.reconnects += 1;
  -
  - Err(last_err)
  }
  }
  