thrift-zookeeper-client
Version:
A module that integrates zookeeper with thrift interfaces with connection pooling logic to make them more robust
117 lines (109 loc) • 4.55 kB
JavaScript
var clusterPool = require('node-pool-cluster');
var _ = require('underscore');
var thrift = require('thrift');
var TIMEOUT_MESSAGE = "ZooKeeper-pool: Connection timeout";
var CLOSE_MESSAGE = "ZooKeeper-pool: Connection closed";
var zookeeper = require('node-zookeeper-client');
var serverSetHelper = {};
/**
* Create a key for storing details the object in the cache.
* Key is created as a combination of zookeeper url, path and service name
*
* @param {Object} zkProps, Object containing zooKeeper server ip, port and path
* @param {string} serviceName, service name to be fetched
* @return {string}, cache key
*/
serverSetHelper.getServiceClientCacheKey = function (zkProps, serviceName) {
return zkProps.zkUrl + "~" + zkProps.zkPath + "~" + serviceName;
};
/**
* Creates a cluster pool of a service.
*
* @param {String} clusterName, name of the cluster(service)
* @param {Object} opts, pool factory options, similar to generic pool
* @return {Object} returns cluster instance
*/
serverSetHelper.initCluster = function (clusterName, opts) {
return clusterPool.initCluster({
name: clusterName,
destroy: function (connection) {
return connection.end();
},
validate: function (connection) {
return !connection.__ended;
},
max: opts.max || 3,
min: opts.min || 0,
refreshIdle: opts.refreshIdle || true,
reapIntervalMillis: opts.reapIntervalMillis || 1000,
idleTimeoutMillis: opts.idleTimeoutMillis || 20000
}, true);
};
/**
* Creates a connection to thrift service running on the specified host.
*
* @param {String} serviceName, Name of the service to be fetched
* @param {Object} serverInfo, info regarding server, its ip and port
* @param {async} async, to enable TFramed protocol
* @param {Function} callBack, function which is called on successful connection or when error occurs.
* @return {EventEmitter|*}
*/
serverSetHelper.createThriftConn = function (serviceName, serverInfo, async, callBack) {
callBack = _.once(callBack);
console.log("[Node-Conn-%s]%s:%d", serviceName, serverInfo.host, serverInfo.port);
var connection = thrift.createConnection(serverInfo.host, serverInfo.port, {
transport: (!!async ? thrift.TFramedTransport : thrift.TBufferedTransport),
protocol: thrift.TBinaryProtocol
});
connection.__ended = false;
connection.on("connect", function () {
connection.connection.setKeepAlive(true);
return callBack(null, connection);
});
connection.on("error", function (err) {
connection.__ended = true;
return callBack(err);
});
connection.on("close", function () {
connection.__ended = true;
return callBack(new Error(CLOSE_MESSAGE));
});
return connection.on("timeout", function () {
connection.__ended = true;
return callBack(new Error(TIMEOUT_MESSAGE));
});
};
/**
* It fetches details of all the running server instances(ip and port) of the specified service.
*
* @param {Object} zkProps, Object containing zooKeeper server ip, port and path
* @param {String} serviceName, Name of the service to be fetched
* @param {String} node, member node of the service containing information of server ip and port
* @param {Object} cluster, cluster of pool for specified service
* @param {async} async, to enable TFramed protocol
* @param cb
*/
serverSetHelper.getNodeDetails = function(zkProps, serviceName, node, cluster, async, cb){
var _pool, zkClient = this;
zkClient.getData(zkProps.zkPath + "/nodeStatus/" + serviceName + "/" + node,
function (event) {
if (zookeeper.Event.NODE_DELETED === event || zookeeper.Event.NODE_DATA_CHANGED === event) {
cluster.removePool(_pool);
serverSetHelper.getNodeDetails().call(zkClient, zkProps, serviceName, node, cluster, async);
}
},
function (err, data) {
var _nodeDetails = JSON.parse(data.toString());
var _host, _port;
if (_nodeDetails.status == "ALIVE") {
_host = _nodeDetails["serviceEndpoint"]["host"];
_port = _nodeDetails["serviceEndpoint"]["port"];
_pool = cluster.addPool(function (callBack) {
return serverSetHelper.createThriftConn(serviceName, {host: _host, port: _port}, async, callBack);
});
}
!!cb && cb();
}
);
};
module.exports = serverSetHelper;