docs: function (poolFactoryOpts, acquireNewPoolOnError, roundRobin) {
          var _this = {}, _cluster = [];
  
          /**
           * Adds server to the cluster.
           *
           * @param {Function} createClient Should create the item to be acquired,
           *   and call it's first callback argument with the generated item as its
           *   argument.
           */
          _this.addPool = function (createClient) {
              var _pool, _poolOptions = _.clone(poolFactoryOpts);
              _poolOptions.create = createClient;
              _pool = GenericPool.Pool(_poolOptions);
              _cluster.push(_pool);
              return _pool;
          };
  
          /**
           * Removes server from the cluster.
           *
           * @param {Object} pool it should be the same server pool, which
           * was returned when adding the server to the cluster.
           * @return {Object} true, if server is successfully removed from cluster, else false.
           */
          _this.removePool = function (pool) {
              var index = _.indexOf(_cluster, pool);
              if (index != -1) {
                  _cluster.splice(index, 1);
                  pool.drain(function () {
                      pool.destroyAllNow();
                  });
                  return true;
              }
              return false;
          };
  
          /**
           * Return total number of created clients in all pools.
           *
           * @return {Number} Number of client connections.
           */
          _this.getPoolSize = function () {
              var count = 0;
              _cluster.forEach(function (pool) {
                  count += pool.getPoolSize();
              });
              return count;
          };
  
          /**
           * Removes all the server pools from cluster
           */
          _this.clear = function () {
              _cluster.forEach(function (pool) {
                  pool.drain(function () {
                      pool.destroyAllNow();
                  });
              });
              _cluster = [];
          };
  
          /**
           * Drains all the pools in the cluster
           */
          _this.drainAll = function () {
              _cluster.forEach(function (pool) {
                  pool.drain(function () {
                      pool.destroyAllNow();
                  });
              });
          };
  
  
          /**
           * Requests a new client from cluster pool. The callback will be called
           * when a new client will be available.
           * Selected pool will also be passed so that you can release the client
           * to the pool after use.
           *
           * @param {Function} callback(err, client, pool)
           *   Callback function to be called after the acquire is successful.
           * @returns {Object} true if pools are not fully utilized, false otherwise.
           */
          _this.acquire = function (callback) {
              if (_cluster.length === 0) {
                  return callback(new Error('No pool server added yet'));
              }
  
              var _poolIndex = 0, _currentPool, _poolMinWaitClient;
              if(roundRobin && _this.__lastIndex){
                  _poolIndex = _this.__lastIndex % _cluster.length;
              }
              var _deadPools = [];
              if(acquireNewPoolOnError && arguments.length >=2 ){
                  _deadPools = arguments[1];
              }
  
              /**
               * Selecting suitable pool to handle request.
               * If there's no waiting queue of requests awaiting to acquire connection
               * then pools are round-robin rotated.
               * If there's a queue, pool with the shortest queue is selected.
               */
              while (_poolIndex < _cluster.length && _cluster.length > _deadPools.length) {
                  _currentPool = _cluster[_poolIndex];
                  if (_deadPools.indexOf(_currentPool) == -1) {
                      if (roundRobin || _currentPool.waitingClientsCount() == 0) {
                          _poolMinWaitClient = _currentPool;
                          _poolIndex++;
                          break;
                      } else {
                          if (!_poolMinWaitClient ||
                              (_currentPool.waitingClientsCount() < _poolMinWaitClient.waitingClientsCount())) {
                              _poolMinWaitClient = _currentPool; //pool with shortest queue
                          }
                      }
                  }
                  _poolIndex++;
              }
              _this.__lastIndex = _poolIndex;
              return !!_poolMinWaitClient && _poolMinWaitClient.acquire(function (err, client) {
                      // Optional check for other pools in cluster
                      // when error occurs acquiring connection in current pool
                      if(acquireNewPoolOnError && !!err && _cluster.length > 1){
                          _deadPools.push(_poolMinWaitClient);
                          _poolMinWaitClient.release(client);
                          return _this.acquire(callback, _deadPools);
                      }
                      return callback(err, client, _poolMinWaitClient);
                  });
          };
  
          return _this;
      }