@Override
  public void run() {
    // The timeout for the network client poll should be a function of the request timeout,
    // as the poll timeout should not cause the request to not time out for a lot longer than the configured request
    // timeout. In the worst case, the request will time out in (request_timeout_ms + poll_timeout_ms), so the poll
    // timeout should be at least an order of magnitude smaller.
    final int NETWORK_CLIENT_POLL_TIMEOUT = routerConfig.routerRequestNetworkTimeoutMs / 10;
    try {
      while (nonBlockingRouter.isOpen.get()) {
        List<RequestInfo> requestsToSend = new ArrayList<>();
        Set<Integer> requestsToDrop = new HashSet<>();
        pollForRequests(requestsToSend, requestsToDrop);

        List<ResponseInfo> responseInfoList = networkClient.sendAndPoll(requestsToSend,
            routerConfig.routerDropRequestOnTimeout ? requestsToDrop : Collections.emptySet(),
            NETWORK_CLIENT_POLL_TIMEOUT);
        responseInfoList.addAll(getNonQuotaCompliantResponses());
        onResponse(responseInfoList);
        responseInfoList.forEach(ResponseInfo::release);
      }
    } catch (Throwable e) {
      logger.error("Aborting, as requestResponseHandlerThread received an unexpected error: ", e);
      routerMetrics.requestResponseHandlerUnexpectedErrorCount.inc();
    } finally {
      networkClient.close();
      shutDownLatch.countDown();
      // Close the router.
      nonBlockingRouter.shutDownOperationControllers();
    }
  }
The RequestResponseHandler thread simply runs in a loop polling the OperationController for any
requests to be sent, and notifies it about network events.
ambry-router/src/main/java/com/github/ambry/router/OperationController.java