You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.9 KiB

'use strict';
var _ = require('lodash');
var Command = require('./command');
var Script = require('./script');
/**
* Commander
*
* This is the base class of Redis, Redis.Cluster and Pipeline
*
* @param {boolean} [options.showFriendlyErrorStack=false] - Whether to show a friendly error stack. Will decrease the performance significantly.
* @constructor
*/
function Commander() {
this.options = _.defaults({}, this.options || {}, {
showFriendlyErrorStack: false
});
this.scriptsSet = {};
}
var commands = _.difference(_.keys(require('../commands'), ['monitor']));
commands.push('sentinel', 'quit');
/**
* Return supported builtin commands
*
* @return {string[]} command list
* @public
*/
Commander.prototype.getBuiltinCommands = function () {
return _.clone(commands);
};
/**
* Create a builtin command
*
* @param {string} commandName - command name
* @return {object} functions
* @public
*/
Commander.prototype.createBuiltinCommand = function (commandName) {
return {
string: generateFunction(commandName, 'utf8'),
buffer: generateFunction(commandName, null)
};
};
_.forEach(commands, function (commandName) {
Commander.prototype[commandName] = generateFunction(commandName, 'utf8');
Commander.prototype[commandName + 'Buffer'] = generateFunction(commandName, null);
});
Commander.prototype.call = generateFunction('utf8');
Commander.prototype.callBuffer = generateFunction(null);
Commander.prototype.send_command = Commander.prototype.call;
/**
* Define a custom command using lua script
*
* @param {string} name - the command name
* @param {object} definition
* @param {string} definition.lua - the lua code
* @param {number} [definition.numberOfKeys=null] - the number of keys.
* If omit, you have to pass the number of keys as the first argument every time you invoke the command
*/
Commander.prototype.defineCommand = function (name, definition) {
var script = new Script(definition.lua, definition.numberOfKeys,
this.options.keyPrefix);
this.scriptsSet[name] = script;
this[name] = generateScriptingFunction(script, 'utf8');
this[name + 'Buffer'] = generateScriptingFunction(script, null);
};
/**
* Send a command
*
* @abstract
* @public
*/
Commander.prototype.sendCommand = function () {};
function generateFunction (_commandName, _encoding) {
if (typeof _encoding === 'undefined') {
_encoding = _commandName;
_commandName = null;
}
return function () {
var firstArgIndex = 0;
var commandName = _commandName;
if (commandName === null) {
commandName = arguments[0];
firstArgIndex = 1;
}
var length = arguments.length;
var lastArgIndex = length - 1;
var callback = arguments[lastArgIndex];
if (typeof callback !== 'function') {
callback = undefined;
} else {
length = lastArgIndex;
}
var args = new Array(length - firstArgIndex);
for (var i = firstArgIndex; i < length; ++i) {
args[i - firstArgIndex] = arguments[i];
}
var options = { replyEncoding: _encoding };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
if (this.options.keyPrefix) {
options.keyPrefix = this.options.keyPrefix;
}
return this.sendCommand(new Command(commandName, args, options, callback));
};
}
function generateScriptingFunction (_script, _encoding) {
return function () {
var length = arguments.length;
var lastArgIndex = length - 1;
var callback = arguments[lastArgIndex];
if (typeof callback !== 'function') {
callback = undefined;
} else {
length = lastArgIndex;
}
var args = new Array(length);
for (var i = 0; i < length; i++) {
args[i] = arguments[i];
}
var options = { replyEncoding: _encoding };
if (this.options.showFriendlyErrorStack) {
options.errorStack = new Error().stack;
}
return _script.execute(this, args, options, callback);
};
}
module.exports = Commander;