docs: function RiakNode(options) {
      events.EventEmitter.call(this);
  
      var self = this;
  
      if (options === undefined) {
          options = {};
      }
  
      Joi.validate(options, schema, function (err, options) {
          if (err) {
              throw err;
          }
          self.remoteAddress = options.remoteAddress;
          self.remotePort = options.remotePort;
          self.minConnections = options.minConnections;
          self.maxConnections = options.maxConnections;
          self.idleTimeout = options.idleTimeout;
          self.connectionTimeout = options.connectionTimeout;
          self.requestTimeout = options.requestTimeout;
          self.state = State.CREATED;
          self.auth = options.auth;
          self.cork = options.cork;
          self.externalLoadBalancer = options.externalLoadBalancer;
          self.healthCheck = options.healthCheck;
      });
  
      this.executeCount = 0;
  
      // This is to facilitate debugging
      this.name = util.format('[RiakNode] (%s:%d-%d)',
          this.remoteAddress, this.remotePort, nid);
      nid++;
  
      // Note: useful for debugging event issues
      // this.setMaxListeners(1);
  
      // private data
      var currentNumConnections = 0;
      var available = [];
  
      // protected funcs
      this._getConnectionFromPool = function (cmd_name) {
          var conn = null;
          do {
              if (available.length === 0) {
                  break;
              }
              conn = available.shift();
              if (conn.closed) {
                  /*
                   * NB: this is expected as connection callbacks can close connections
                   * while they remain within the connection pool
                   */
                  logger.debug('%s execute of %s attempted on closed connection', this.name, cmd_name);
                  conn.executeDone();
                  conn = null;
              }
          } while (!conn);
          return conn;
      };
  
      this._returnConnectionToPool = function (conn) {
          if (this.state < State.SHUTTING_DOWN) {
              conn.executeDone();
              available.unshift(conn);
              logger.debug("%s _returnConnectionToPool a: %d, cnc: %d",
                  this.name, available.length, currentNumConnections);
          } else {
              logger.debug('%s connection returned to pool during shutdown.', this.name);
              this._decrementConnectionCount();
              conn.close();
          }
      };
  
      this._decrementConnectionCount = function () {
          if ((currentNumConnections - 1) < 0) {
              logger.debug("%s cnc will decrement less than zero! (%d)",
                  this.name, currentNumConnections);
          }
          currentNumConnections--;
      };
  
      this._executeAllowed = function () {
          return this.state === State.RUNNING;
      };
  
      this._createNewConnectionAllowed = function () {
          return this.state === State.RUNNING &&
                 currentNumConnections < this.maxConnections;
      };
  
      function expireIdleConnections(name, minConnections, idleTimeout) {
          logger.debug("%s expiring idle connections", name);
          var now = Date.now();
          var count = 0;
          var na = [];
          var conn = null;
          while (available.length) {
              conn = available.shift();
              // NB: don't keep any closed connections around.
              if (conn.closed) {
                  conn.executeDone();
                  conn = null;
                  continue;
              }
  
              // NB: if a connection is executing, keep it around
              if (conn.inFlight) {
                  na.push(conn);
                  continue;
              }
  
              // NB: don't expire past minConnections
              if (currentNumConnections <= minConnections) {
                  na.push(conn);
                  continue;
              }
  
              if ((now - conn.lastUsed) >= idleTimeout) {
                  /* jshint validthis:true */
                  this._decrementConnectionCount();
                  conn.close();
                  count++;
                  continue;
              }
  
              na.push(conn);
          }
          available = na;
          logger.debug("%s expired %d connections.", name, count);
      }
  
      var expireTimer = null;
      this._startIdleExpiration = function () {
          var cb = expireIdleConnections.bind(this, this.name, this.minConnections, this.idleTimeout);
          expireTimer = setInterval(cb, 5000);
      };
  
      this._stopIdleExpiration = function () {
          clearInterval(expireTimer);
      };
  
      this._createNewConnection = function (postConnectFunc, postFailFunc, healthCheck) {
          currentNumConnections++;
  
          var conn = new RiakConnection({
              remoteAddress : this.remoteAddress,
              remotePort : this.remotePort,
              connectionTimeout : this.connectionTimeout,
              requestTimeout : this.requestTimeout,
              auth: this.auth,
              healthCheck: healthCheck,
              cork: this.cork
          });
  
          var self = this;
  
          conn.on('connected', function (conn) {
              logger.debug("%s conn.on-connected", this.name);
              conn.on('responseReceived', self._responseReceived.bind(self));
              conn.on('connectionClosed', self._connectionClosed.bind(self));
              postConnectFunc(conn);
          });
  
          conn.on('connectFailed', function (conn, err){
              // NB: when connectFailed is raised, conn is already closed
              logger.debug("%s conn.on-connectFailed", this.name);
              self._decrementConnectionCount();
              postFailFunc(err);
          });
  
          conn.connect();
      };
  
      this._makeNewConnectionFunc = function (node) {
          var f = function (async_cb) {
              var postConnect = function (conn) {
                  node._returnConnectionToPool(conn);
                  async_cb(null, true);
              };
              var postFail = function (err) {
                  async_cb(err, false);
              };
              node._createNewConnection(postConnect, postFail);
          };
          return f;
      };
  
      var hcb = backoff.fibonacci({
          initialDelay: 10,
          maxDelay: 5000
      });
      function initHealthChecker(self) {
          logger.debug("%s initializing health checker", self.name);
          var hcFunc = self.healthCheck;
  
          function hcSuccess(newConn) {
              hcb.reset();
              self._returnConnectionToPool(newConn);
              self.state = State.RUNNING;
              logger.debug("%s health check success", self.name);
              self.emit(EVT_SC, self, self.state);
          }
  
          function hcFailed(err) {
              logger.debug("%s failed health check:", err);
              // NB: healthcheck interval *should* be less than re-try interval
              hcb.backoff();
          }
  
          function hcReady(n, d) {
              self._createNewConnection(hcSuccess, hcFailed, hcFunc);
          }
  
          function hcBackoffHandler(n, d) {
              logger.debug("%s running health check %d, delay: %d", self.name, n, d);
          }
  
          hcb.on('ready', hcReady);
          hcb.on('backoff', hcBackoffHandler);
      }
      initHealthChecker(this);
  
      this._doHealthCheck = function () {
          switch (this.state) {
              case State.HEALTH_CHECKING:
                  if (this.externalLoadBalancer) {
                      logger.error('%s already in health check, external load balancer:',
                          this.name, this.externalLoadBalancer);
                  } else {
                      logger.debug("%s already in health check", this.name);
                  }
                  break;
              case State.RUNNING:
                  if (this.externalLoadBalancer) {
                      logger.warn('%s would have health checked, external load balancer:',
                          this.name, this.externalLoadBalancer);
                  } else {
                      this.state = State.HEALTH_CHECKING;
                      this.emit(EVT_SC, this, this.state);
                      hcb.backoff();
                  }
                  break;
              default:
                  logger.warn('%s health check attempted in state:',
                      this.name, stateNames[this.state]);
          }
      };
  
      var sdb = backoff.fibonacci({
          initialDelay: 125,
          maxDelay: 1000
      });
      sdb.failAfter(10);
      var sdbHandlersInitialized = false;
      function runShutdown(self, callback) {
          var conns = [];
          function closeConnections() {
              logger.debug("%s closing %d connections",
                  self.name, currentNumConnections);
              var conn = null;
              while (available.length) {
                  conn = available.shift();
                  if (conn.closed) {
                      conn.executeDone();
                      conn = null;
                  } else {
                      self._decrementConnectionCount();
                      conn.close();
                      conns.push(conn);
                  }
              }
              logger.debug("%s closed connections (cnc: %d)",
                  self.name, currentNumConnections);
          }
  
          function areConnsClosed() {
              closeConnections();
              var conns_closed = true;
              for (var i = 0; i < conns.length; i++) {
                  var c = conns[i];
                  if (!c.closed) {
                      conns_closed = false;
                      break;
                  }
              }
              if (currentNumConnections > 0) {
                  conns_closed = false;
              }
              return conns_closed;
          }
  
          function nodeShutdown() {
              sdb.reset();
              self.state = State.SHUTDOWN;
              logger.debug("%s shut down.", self.name);
              if (self.executeCount !== 0) {
                  logger.warn('%s execution count (%d) NOT ZERO at shutdown',
                      self.name, self.executeCount);
              }
              if (currentNumConnections !== 0) {
                  logger.warn('%s connection count (%d) NOT ZERO at shutdown',
                      self.name, currentNumConnections);
              }
              self.emit(EVT_SC, self, self.state);
              self.removeAllListeners();
              if (callback) {
                  callback(null, self.state);
              }
          }
  
          function sdReady() {
              if (areConnsClosed()) {
                  nodeShutdown();
              } else {
                  logger.debug("%s connections still not closed", self.name);
                  sdb.backoff();
              }
          }
  
          function sdBackoffHandler(n, d) {
              logger.debug("%s running shutdown %d, delay: %d", self.name, n, d);
          }
  
          function sdFailHandler() {
              logger.warn("%s shutting down after max tries", self.name);
              nodeShutdown();
          }
  
          if (!sdbHandlersInitialized) {
              sdb.on('ready', sdReady);
              sdb.on('backoff', sdBackoffHandler);
              sdb.on('fail', sdFailHandler);
              sdbHandlersInitialized = true;
          }
  
          if (areConnsClosed()) {
              nodeShutdown();
          } else {
              sdb.backoff();
          }
      }
  
      this._shutdown = function(callback) {
          runShutdown(this, callback);
      };
  
      this._stateCheck = function (allowedStates) {
          return utils.stateCheck(this.name, this.state,
              allowedStates, stateNames);
      };
  }