1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

Refactor command parsing

This commit is contained in:
Ruben Bridgewater
2016-05-27 17:32:42 +02:00
parent 899f9b7fe4
commit 8b6f2dd35e
10 changed files with 106 additions and 123 deletions

View File

@@ -2,6 +2,7 @@
var Queue = require('double-ended-queue');
var utils = require('./utils');
var Command = require('./command');
function Multi (client, args) {
this._client = client;
@@ -20,18 +21,23 @@ function Multi (client, args) {
}
}
function pipeline_transaction_command (self, command, args, index, cb, call_on_write) {
function pipeline_transaction_command (self, command_obj, index) {
// Queueing is done first, then the commands are executed
self._client.send_command(command, args, function (err, reply) {
var tmp = command_obj.callback;
command_obj.callback = function (err, reply) {
// Ignore the multi command. This is applied by node_redis and the user does not benefit by it
if (err && index !== -1) {
if (cb) {
cb(err);
if (tmp) {
tmp(err);
}
err.position = index;
self.errors.push(err);
}
});
// Keep track of who wants buffer responses:
// By the time the callback is called the command_obj got the buffer_args attribute attached
self.wants_buffers[index] = command_obj.buffer_args;
};
self._client.internal_send_command(command_obj);
}
Multi.prototype.exec_atomic = Multi.prototype.EXEC_ATOMIC = Multi.prototype.execAtomic = function exec_atomic (callback) {
@@ -42,7 +48,7 @@ Multi.prototype.exec_atomic = Multi.prototype.EXEC_ATOMIC = Multi.prototype.exec
};
function multi_callback (self, err, replies) {
var i = 0, args;
var i = 0, command_obj;
if (err) {
err.errors = self.errors;
@@ -56,22 +62,22 @@ function multi_callback (self, err, replies) {
}
if (replies) {
while (args = self.queue.shift()) {
while (command_obj = self.queue.shift()) {
if (replies[i] instanceof Error) {
var match = replies[i].message.match(utils.err_code);
// LUA script could return user errors that don't behave like all other errors!
if (match) {
replies[i].code = match[1];
}
replies[i].command = args[0].toUpperCase();
if (typeof args[2] === 'function') {
args[2](replies[i]);
replies[i].command = command_obj.command.toUpperCase();
if (typeof command_obj.callback === 'function') {
command_obj.callback(replies[i]);
}
} else {
// If we asked for strings, even in detect_buffers mode, then return strings:
replies[i] = self._client.handle_reply(replies[i], args[0], self.wants_buffers[i]);
if (typeof args[2] === 'function') {
args[2](null, replies[i]);
replies[i] = self._client.handle_reply(replies[i], command_obj.command, self.wants_buffers[i]);
if (typeof command_obj.callback === 'function') {
command_obj.callback(null, replies[i]);
}
}
i++;
@@ -98,30 +104,16 @@ Multi.prototype.exec_transaction = function exec_transaction (callback) {
self.callback = callback;
self._client.cork();
self.wants_buffers = new Array(len);
pipeline_transaction_command(self, 'multi', [], -1);
pipeline_transaction_command(self, new Command('multi', []), -1);
// Drain queue, callback will catch 'QUEUED' or error
for (var index = 0; index < len; index++) {
// The commands may not be shifted off, since they are needed in the result handler
var command_obj = self.queue.get(index);
var command = command_obj[0];
var cb = command_obj[2];
var call_on_write = command_obj.length === 4 ? command_obj[3] : undefined;
// Keep track of who wants buffer responses:
if (self._client.options.detect_buffers) {
self.wants_buffers[index] = false;
for (var i = 0; i < command_obj[1].length; i += 1) {
if (command_obj[1][i] instanceof Buffer) {
self.wants_buffers[index] = true;
break;
}
}
}
pipeline_transaction_command(self, command, command_obj[1], index, cb, call_on_write);
pipeline_transaction_command(self, self.queue.get(index), index);
}
self._client.internal_send_command('exec', [], function (err, replies) {
self._client.internal_send_command(new Command('exec', [], function (err, replies) {
multi_callback(self, err, replies);
});
}));
self._client.uncork();
return !self._client.should_buffer;
};
@@ -144,16 +136,17 @@ Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = funct
var len = self.queue.length;
var index = 0;
var command_obj;
if (len === 0) {
utils.reply_in_order(self._client, callback, null, []);
return !self._client.should_buffer;
}
self._client.cork();
if (!callback) {
while (command_obj = self.queue.shift()) {
self._client.internal_send_command(command_obj[0], command_obj[1], command_obj[2], (command_obj.length === 4 ? command_obj[3] : undefined));
self._client.internal_send_command(command_obj);
}
self._client.uncork();
return !self._client.should_buffer;
} else if (len === 0) {
utils.reply_in_order(self._client, callback, null, []);
return !self._client.should_buffer;
}
var callback_without_own_cb = function (err, res) {
if (err) {
@@ -175,18 +168,15 @@ Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = funct
};
self.results = [];
while (command_obj = self.queue.shift()) {
var command = command_obj[0];
var call_on_write = command_obj.length === 4 ? command_obj[3] : undefined;
var cb;
if (typeof command_obj[2] === 'function') {
cb = batch_callback(self, command_obj[2], index);
if (typeof command_obj.callback === 'function') {
command_obj.callback = batch_callback(self, command_obj.callback, index);
} else {
cb = callback_without_own_cb;
command_obj.callback = callback_without_own_cb;
}
if (typeof callback === 'function' && index === len - 1) {
cb = last_callback(cb);
command_obj.callback = last_callback(command_obj.callback);
}
this._client.internal_send_command(command, command_obj[1], cb, call_on_write);
this._client.internal_send_command(command_obj);
index++;
}
self._client.uncork();