HTTPSession::readTimeoutExpired() noexcept {
  VLOG(3) << "session-level timeout on " << *this;

  if (liveTransactions_ != 0) {
    // There's at least one open transaction with a read timeout scheduled.
    // We got here because the session timeout == the transaction timeout.
    // Ignore, since the transaction is going to timeout very soon.
    VLOG(4) << *this <<
        "ignoring session timeout, transaction timeout imminent";
    resetTimeout();
    return;
  }

  if (!transactions_.empty()) {
    // There are one or more transactions, but none of them are live.
    // That's valid if they've all received their full ingress messages
    // and are waiting for their Handlers to process those messages.
    VLOG(4) << *this <<
        "ignoring session timeout, no transactions awaiting reads";
    resetTimeout();
    return;
  }

  VLOG(4) << *this << " Timeout with nothing pending";

  setCloseReason(ConnectionCloseReason::TIMEOUT);
  auto controller = getController();
  if (controller) {
    timeout_.scheduleTimeout(&drainTimeout_,
                             controller->getGracefulShutdownTimeout());
  }
  notifyPendingShutdown();
}
HTTPSession::readTimeoutExpired() noexcept {
  VLOG(3) << "session-level timeout on " << *this;

  if (liveTransactions_ != 0) {
     
     
     
    VLOG(4) << *this <<
        "ignoring session timeout, transaction timeout imminent";
    resetTimeout();
    return;
  }

  if (!transactions_.empty()) {
     
     
     
    VLOG(4) << *this <<
        "ignoring session timeout, no transactions awaiting reads";
    resetTimeout();
    return;
  }

  VLOG(4) << *this << " Timeout with nothing pending";

  setCloseReason(ConnectionCloseReason::TIMEOUT);
  auto controller = getController();
  if (controller) {
    timeout_.scheduleTimeout(&drainTimeout_,
                             controller->getGracefulShutdownTimeout());
  }
  notifyPendingShutdown();
}