Skip to content

Commit 8b6f2dd

Browse files
author
Ruben Bridgewater
committed
Refactor command parsing
1 parent 899f9b7 commit 8b6f2dd

File tree

10 files changed

+106
-123
lines changed

10 files changed

+106
-123
lines changed

index.js

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ var util = require('util');
66
var utils = require('./lib/utils');
77
var Queue = require('double-ended-queue');
88
var errorClasses = require('./lib/customErrors');
9-
var Command = require('./lib/command').Command;
10-
var OfflineCommand = require('./lib/command').OfflineCommand;
119
var EventEmitter = require('events');
1210
var Parser = require('redis-parser');
1311
var commands = require('redis-commands');
@@ -156,6 +154,7 @@ function RedisClient (options, stream) {
156154
this.times_connected = 0;
157155
this.buffers = options.return_buffers || options.detect_buffers;
158156
this.options = options;
157+
this.old_state = {};
159158
this.reply = 'ON'; // Returning replies is the default
160159
// Init parser
161160
this.reply_parser = create_parser(this);
@@ -443,14 +442,10 @@ RedisClient.prototype.on_ready = function () {
443442

444443
// Restore modal commands from previous connection. The order of the commands is important
445444
if (this.selected_db !== undefined) {
446-
this.internal_send_command('select', [this.selected_db]);
445+
this.select(this.selected_db);
447446
}
448-
if (this.old_state !== null) {
449-
this.monitoring = this.old_state.monitoring;
450-
this.pub_sub_mode = this.old_state.pub_sub_mode;
451-
}
452-
if (this.monitoring) { // Monitor has to be fired before pub sub commands
453-
this.internal_send_command('monitor', []); // The state is still set
447+
if (this.old_state.monitoring) { // Monitor has to be fired before pub sub commands
448+
this.monitor();
454449
}
455450
var callback_count = Object.keys(this.subscription_set).length;
456451
if (!this.options.disable_resubscribing && callback_count) {
@@ -466,8 +461,8 @@ RedisClient.prototype.on_ready = function () {
466461
debug('Sending pub/sub on_ready commands');
467462
for (var key in this.subscription_set) {
468463
var command = key.slice(0, key.indexOf('_'));
469-
var args = self.subscription_set[key];
470-
self.internal_send_command(command, [args], callback);
464+
var args = this.subscription_set[key];
465+
this[command]([args], callback);
471466
}
472467
this.send_offline_queue();
473468
return;
@@ -530,7 +525,7 @@ RedisClient.prototype.ready_check = function () {
530525
RedisClient.prototype.send_offline_queue = function () {
531526
for (var command_obj = this.offline_queue.shift(); command_obj; command_obj = this.offline_queue.shift()) {
532527
debug('Sending offline command: ' + command_obj.command);
533-
this.internal_send_command(command_obj.command, command_obj.args, command_obj.callback, command_obj.call_on_write);
528+
this.internal_send_command(command_obj);
534529
}
535530
this.drain();
536531
};
@@ -575,8 +570,7 @@ RedisClient.prototype.connection_gone = function (why, error) {
575570
this.pipeline = false;
576571

577572
var state = {
578-
monitoring: this.monitoring,
579-
pub_sub_mode: this.pub_sub_mode
573+
monitoring: this.monitoring
580574
};
581575
this.old_state = state;
582576
this.monitoring = false;
@@ -834,7 +828,6 @@ RedisClient.prototype.return_reply = function (reply) {
834828

835829
function handle_offline_command (self, command_obj) {
836830
var command = command_obj.command;
837-
var callback = command_obj.callback;
838831
var err, msg;
839832
if (self.closing || !self.enable_offline_queue) {
840833
command = command.toUpperCase();
@@ -852,10 +845,10 @@ function handle_offline_command (self, command_obj) {
852845
code: 'NR_CLOSED',
853846
command: command
854847
});
855-
if (command_obj.args && command_obj.args.length) {
848+
if (command_obj.args.length) {
856849
err.args = command_obj.args;
857850
}
858-
utils.reply_in_order(self, callback, err);
851+
utils.reply_in_order(self, command_obj.callback, err);
859852
} else {
860853
debug('Queueing ' + command + ' for next server connection.');
861854
self.offline_queue.push(command_obj);
@@ -865,22 +858,23 @@ function handle_offline_command (self, command_obj) {
865858

866859
// Do not call internal_send_command directly, if you are not absolutly certain it handles everything properly
867860
// e.g. monitor / info does not work with internal_send_command only
868-
RedisClient.prototype.internal_send_command = function (command, args, callback, call_on_write) {
869-
var arg, prefix_keys, command_obj;
861+
RedisClient.prototype.internal_send_command = function (command_obj) {
862+
var arg, prefix_keys;
870863
var i = 0;
871864
var command_str = '';
865+
var args = command_obj.args;
866+
var command = command_obj.command;
872867
var len = args.length;
873868
var big_data = false;
874-
var buffer_args = false;
875869
var args_copy = new Array(len);
876870

877-
if (process.domain && callback) {
878-
callback = process.domain.bind(callback);
871+
if (process.domain && command_obj.callback) {
872+
command_obj.callback = process.domain.bind(command_obj.callback);
879873
}
880874

881875
if (this.ready === false || this.stream.writable === false) {
882876
// Handle offline commands right away
883-
handle_offline_command(this, new OfflineCommand(command, args, callback, call_on_write));
877+
handle_offline_command(this, command_obj);
884878
return false; // Indicate buffering
885879
}
886880

@@ -905,7 +899,7 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
905899
args_copy[i] = 'null'; // Backwards compatible :/
906900
} else if (Buffer.isBuffer(args[i])) {
907901
args_copy[i] = args[i];
908-
buffer_args = true;
902+
command_obj.buffer_args = true;
909903
big_data = true;
910904
} else {
911905
this.warn(
@@ -927,8 +921,6 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
927921
args_copy[i] = '' + args[i];
928922
}
929923
}
930-
// Pass the original args to make sure in error cases the original arguments are returned
931-
command_obj = new Command(command, args, buffer_args, callback);
932924

933925
if (this.options.prefix) {
934926
prefix_keys = commands.getKeyIndexes(command, args_copy);
@@ -967,8 +959,8 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
967959
debug('send_command: buffer send ' + arg.length + ' bytes');
968960
}
969961
}
970-
if (call_on_write) {
971-
call_on_write();
962+
if (command_obj.call_on_write) {
963+
command_obj.call_on_write();
972964
}
973965
// Handle `CLIENT REPLY ON|OFF|SKIP`
974966
// This has to be checked after call_on_write
@@ -978,8 +970,8 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
978970
} else {
979971
// Do not expect a reply
980972
// Does this work in combination with the pub sub mode?
981-
if (callback) {
982-
utils.reply_in_order(this, callback, null, undefined, this.command_queue);
973+
if (command_obj.callback) {
974+
utils.reply_in_order(this, command_obj.callback, null, undefined, this.command_queue);
983975
}
984976
if (this.reply === 'SKIP') {
985977
this.reply = 'SKIP_ONE_MORE';

lib/command.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
'use strict';
22

3-
// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using
4-
// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots.
5-
function Command (command, args, buffer_args, callback) {
6-
this.command = command;
7-
this.args = args;
8-
this.buffer_args = buffer_args;
9-
this.callback = callback;
10-
}
113

12-
function OfflineCommand (command, args, callback, call_on_write) {
4+
function Command (command, args, callback, call_on_write) {
135
this.command = command;
146
this.args = args;
7+
this.buffer_args = false;
158
this.callback = callback;
169
this.call_on_write = call_on_write;
1710
}
1811

19-
module.exports = {
20-
Command: Command,
21-
OfflineCommand: OfflineCommand
22-
};
12+
module.exports = Command;

lib/commands.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var commands = require('redis-commands');
44
var Multi = require('./multi');
55
var RedisClient = require('../').RedisClient;
6+
var Command = require('./command');
67

78
// TODO: Rewrite this including the invidual commands into a Commands class
89
// that provided a functionality to add new commands to the client
@@ -42,7 +43,7 @@ commands.list.forEach(function (command) {
4243
arr[i] = arguments[i];
4344
}
4445
}
45-
return this.internal_send_command(command, arr, callback);
46+
return this.internal_send_command(new Command(command, arr, callback));
4647
};
4748
Object.defineProperty(RedisClient.prototype[command], 'name', {
4849
value: command
@@ -82,7 +83,7 @@ commands.list.forEach(function (command) {
8283
arr[i] = arguments[i];
8384
}
8485
}
85-
this.queue.push([command, arr, callback]);
86+
this.queue.push(new Command(command, arr, callback));
8687
return this;
8788
};
8889
Object.defineProperty(Multi.prototype[command], 'name', {

lib/extendedApi.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var utils = require('./utils');
44
var debug = require('./debug');
55
var RedisClient = require('../').RedisClient;
6+
var Command = require('./command');
67
var noop = function () {};
78

89
/**********************************************
@@ -36,7 +37,7 @@ RedisClient.prototype.send_command = RedisClient.prototype.sendCommand = functio
3637
// but this might change from time to time and at the moment there's no good way to distinguishe them
3738
// from each other, so let's just do it do it this way for the time being
3839
if (command === 'multi' || typeof this[command] !== 'function') {
39-
return this.internal_send_command(command, args, callback);
40+
return this.internal_send_command(new Command(command, args, callback));
4041
}
4142
if (typeof callback === 'function') {
4243
args = args.concat([callback]); // Prevent manipulating the input array

0 commit comments

Comments
 (0)