@Override
  public void run() {
    ReportProcedureDoneRequest.Builder builder = ReportProcedureDoneRequest.newBuilder();
    int tries = 0;
    while (!server.isStopped()) {
      if (builder.getResultCount() == 0) {
        try {
          builder.addResult(results.take());
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          continue;
        }
      }
      while (builder.getResultCount() < MAX_BATCH) {
        RemoteProcedureResult result = results.poll();
        if (result == null) {
          break;
        }
        builder.addResult(result);
      }
      ReportProcedureDoneRequest request = builder.build();
      try {
        server.reportProcedureDone(builder.build());
        builder.clear();
        tries = 0;
      } catch (IOException e) {
        boolean pause =
          e instanceof ServerNotRunningYetException || e instanceof PleaseHoldException;
        long pauseTime;
        if (pause) {
          // Do backoff else we flood the Master with requests.
          pauseTime = ConnectionUtils.getPauseTime(server.getRetryPauseTime(), tries);
        } else {
          pauseTime = server.getRetryPauseTime(); // Reset.
        }
        LOG.info("Failed procedure report " + TextFormat.shortDebugString(request) + "; retry (#"
          + tries + ")"
          + (pause
            ? " after " + pauseTime + "ms delay (Master is coming online...)."
            : " immediately."),
          e);
        Threads.sleep(pauseTime);
        tries++;
      }
    }
  }
A thread which calls {@code reportProcedureDone} to tell master the result of a remote procedure.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RemoteProcedureResultReporter.java