heroku-debug
Version:
debugging plugin for the CLI
140 lines (122 loc) • 3.4 kB
JavaScript
;
var util = require('util');
var utils = require('../utils');
var EventEmitter = require('events').EventEmitter;
var _ = require('lodash');
var Redis = require('../redis');
function ConnectionPool(redisOptions) {
EventEmitter.call(this);
this.redisOptions = redisOptions;
// master + slave = all
this.nodes = {
all: {},
master: {},
slave: {}
};
this.specifiedOptions = {};
}
util.inherits(ConnectionPool, EventEmitter);
/**
* Find or create a connection to the node
*
* @param {Object} node - the node to connect to
* @param {boolean} [readOnly=false] - whether the node is a slave
* @return {Redis}
* @public
*/
ConnectionPool.prototype.findOrCreate = function (node, readOnly) {
setKey(node);
readOnly = Boolean(readOnly);
if (this.specifiedOptions[node.key]) {
_.assign(node, this.specifiedOptions[node.key]);
} else {
this.specifiedOptions[node.key] = node;
}
var redis;
if (this.nodes.all[node.key]) {
redis = this.nodes.all[node.key];
if (redis.options.readOnly !== readOnly) {
redis.options.readOnly = readOnly;
redis[readOnly ? 'readonly' : 'readwrite']().catch(_.noop);
if (readOnly) {
delete this.nodes.master[node.key];
this.nodes.slave[node.key] = redis;
} else {
delete this.nodes.slave[node.key];
this.nodes.master[node.key] = redis;
}
}
} else {
redis = new Redis(_.defaults({
retryStrategy: null,
readOnly: readOnly
}, node, this.redisOptions, { lazyConnect: true }));
this.nodes.all[node.key] = redis;
this.nodes[readOnly ? 'slave' : 'master'][node.key] = redis;
var _this = this;
redis.once('end', function () {
delete _this.nodes.all[node.key];
delete _this.nodes.master[node.key];
delete _this.nodes.slave[node.key];
_this.emit('-node', redis);
if (!Object.keys(_this.nodes.all).length) {
_this.emit('drain');
}
});
this.emit('+node', redis);
redis.on('error', function (error) {
_this.emit('nodeError', error);
});
}
return redis;
};
/**
* Reset the pool with a set of nodes.
* The old node will be removed.
*
* @param {Object[]} nodes
* @public
*/
ConnectionPool.prototype.reset = function (nodes) {
var newNodes = {};
nodes.forEach(function (node) {
var options = {};
if (typeof node === 'object') {
_.defaults(options, node);
} else if (typeof node === 'string') {
_.defaults(options, utils.parseURL(node));
} else if (typeof node === 'number') {
options.port = node;
} else {
throw new Error('Invalid argument ' + node);
}
if (typeof options.port === 'string') {
options.port = parseInt(options.port, 10);
}
delete options.db;
setKey(options);
newNodes[options.key] = options;
}, this);
var _this = this;
Object.keys(this.nodes.all).forEach(function (key) {
if (!newNodes[key]) {
_this.nodes.all[key].disconnect();
}
});
Object.keys(newNodes).forEach(function (key) {
_this.findOrCreate(newNodes[key], newNodes[key].readOnly);
});
};
/**
* Set key property
*
* @private
*/
function setKey(node) {
node = node || {};
node.port = node.port || 6379;
node.host = node.host || '127.0.0.1';
node.key = node.key || node.host + ':' + node.port;
return node;
}
module.exports = ConnectionPool;