code: void waitForNewEpoch()
        throws InterruptedException, TimeoutException, IOException {
      MessageTuple tuple = filter.getExpectedMessage(MessageType.NEW_EPOCH,
                                                     this.electedLeader,
                                                     config.getTimeoutMs());
      Message msg = tuple.getMessage();
      String source = tuple.getServerId();
      ZabMessage.NewEpoch epoch = msg.getNewEpoch();
      if (epoch.getNewEpoch() < persistence.getProposedEpoch()) {
        LOG.error("New epoch {} from {} is smaller than last received "
                  + "proposed epoch {}",
                  epoch.getNewEpoch(),
                  source,
                  persistence.getProposedEpoch());
        throw new RuntimeException("New epoch is smaller than current one.");
      }
      // Updates follower's last proposed epoch.
      persistence.setProposedEpoch(epoch.getNewEpoch());
      // Updates follower's sync timeout.
      setSyncTimeoutMs(epoch.getSyncTimeout());
      LOG.debug("Received the new epoch proposal {} from {}.",
                epoch.getNewEpoch(),
                source);
      Zxid zxid = persistence.getLatestZxid();
      // Sends ACK to leader.
      sendMessage(this.electedLeader,
                  MessageBuilder.buildAckEpoch(persistence.getAckEpoch(),
                                               zxid));
    }
docs: Waits until receives the NEWEPOCH message from leader.
  
  @throws InterruptedException if anything wrong happens.
  @throws TimeoutException in case of timeout.
  @throws IOException in case of IO failure.