Skip to content

Commit 614e35a

Browse files
author
Ruben Bridgewater
committed
Move multi; commands; createClient code into separate files
1 parent ce80569 commit 614e35a

File tree

7 files changed

+586
-26
lines changed

7 files changed

+586
-26
lines changed

lib/command.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using
44
// 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) {
5+
function Command(command, args, callback) {
66
this.command = command;
77
this.args = args;
8-
this.buffer_args = buffer_args;
8+
this.buffer_args = false;
99
this.callback = callback;
1010
}
1111

lib/commands.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
'use strict';
2+
3+
var commands = require('redis-commands');
4+
var Multi = require('./multi');
5+
var RedisClient = require('../').RedisClient;
6+
7+
// TODO: Rewrite this including the invidual commands into a Commands class
8+
// that provided a functionality to add new commands to the client
9+
10+
commands.list.forEach(function (command) {
11+
12+
// Do not override existing functions
13+
if (!RedisClient.prototype[command]) {
14+
RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command] = function () {
15+
var arr;
16+
var len = arguments.length;
17+
var callback;
18+
var i = 0;
19+
if (Array.isArray(arguments[0])) {
20+
arr = arguments[0];
21+
if (len === 2) {
22+
callback = arguments[1];
23+
}
24+
} else if (len > 1 && Array.isArray(arguments[1])) {
25+
if (len === 3) {
26+
callback = arguments[2];
27+
}
28+
len = arguments[1].length;
29+
arr = new Array(len + 1);
30+
arr[0] = arguments[0];
31+
for (; i < len; i += 1) {
32+
arr[i + 1] = arguments[1][i];
33+
}
34+
} else {
35+
// The later should not be the average use case
36+
if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
37+
len--;
38+
callback = arguments[len];
39+
}
40+
arr = new Array(len);
41+
for (; i < len; i += 1) {
42+
arr[i] = arguments[i];
43+
}
44+
}
45+
return this.send_command(command, arr, callback);
46+
};
47+
}
48+
49+
// Do not override existing functions
50+
if (!Multi.prototype[command]) {
51+
Multi.prototype[command.toUpperCase()] = Multi.prototype[command] = function () {
52+
var arr;
53+
var len = arguments.length;
54+
var callback;
55+
var i = 0;
56+
if (Array.isArray(arguments[0])) {
57+
arr = arguments[0];
58+
if (len === 2) {
59+
callback = arguments[1];
60+
}
61+
} else if (len > 1 && Array.isArray(arguments[1])) {
62+
if (len === 3) {
63+
callback = arguments[2];
64+
}
65+
len = arguments[1].length;
66+
arr = new Array(len + 1);
67+
arr[0] = arguments[0];
68+
for (; i < len; i += 1) {
69+
arr[i + 1] = arguments[1][i];
70+
}
71+
} else {
72+
// The later should not be the average use case
73+
if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
74+
len--;
75+
callback = arguments[len];
76+
}
77+
arr = new Array(len);
78+
for (; i < len; i += 1) {
79+
arr[i] = arguments[i];
80+
}
81+
}
82+
this.queue.push([command, arr, callback]);
83+
return this;
84+
};
85+
}
86+
});

lib/createClient.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict';
2+
3+
var utils = require('./utils');
4+
var URL = require('url');
5+
6+
module.exports = function createClient (port_arg, host_arg, options) {
7+
8+
if (typeof port_arg === 'number' || typeof port_arg === 'string' && /^\d+$/.test(port_arg)) {
9+
10+
var host;
11+
if (typeof host_arg === 'string') {
12+
host = host_arg;
13+
} else {
14+
options = options || host_arg;
15+
}
16+
options = utils.clone(options);
17+
options.host = host || options.host;
18+
options.port = port_arg;
19+
20+
} else if (typeof port_arg === 'string' || port_arg && port_arg.url) {
21+
22+
options = utils.clone(port_arg.url ? port_arg : host_arg || options);
23+
var parsed = URL.parse(port_arg.url || port_arg, true, true);
24+
25+
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
26+
if (parsed.hostname || parsed.slashes) { // The host might be an empty string
27+
if (parsed.auth) {
28+
options.password = parsed.auth.split(':')[1];
29+
}
30+
if (!/^([a-z]+:)?\/\//i.test(parsed.href)) {
31+
throw new Error('Connection string must use the "redis:" protocol or begin with slashes //');
32+
}
33+
if (parsed.pathname && parsed.pathname !== '/') {
34+
options.db = parsed.pathname.substr(1);
35+
}
36+
options.host = parsed.hostname;
37+
options.port = parsed.port;
38+
39+
if (parsed.search !== '') {
40+
var elem;
41+
for (elem in parsed.query) { // jshint ignore: line
42+
// If options are passed twice, only the parsed options will be used
43+
if (elem in options) {
44+
if (options[elem] === parsed.query[elem]) {
45+
console.warn('node_redis: WARNING: You passed the ' + elem + ' option twice!');
46+
} else {
47+
throw new Error('The ' + elem + ' option is added twice and does not match');
48+
}
49+
}
50+
options[elem] = parsed.query[elem];
51+
}
52+
}
53+
} else {
54+
options.path = port_arg;
55+
}
56+
57+
} else if (typeof port_arg === 'object' || port_arg === undefined) {
58+
options = utils.clone(port_arg || options);
59+
options.host = options.host || host_arg;
60+
}
61+
62+
if (!options) {
63+
throw new Error('Unknown type of connection in createClient()');
64+
}
65+
66+
return options;
67+
};

lib/debug.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
var index = require('../');
4+
5+
function debug (msg) {
6+
if (index.debug_mode) {
7+
console.error(msg);
8+
}
9+
}
10+
11+
module.exports = debug;

lib/individualCommands.js

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
'use strict';
2+
3+
var utils = require('./utils');
4+
var debug = require('./debug');
5+
var Multi = require('./multi');
6+
var no_password_is_set = /no password is set/;
7+
var RedisClient = require('../').RedisClient;
8+
9+
/********************************
10+
Replace built-in redis functions
11+
********************************/
12+
13+
RedisClient.prototype.multi = RedisClient.prototype.MULTI = function multi (args) {
14+
var multi = new Multi(this, args);
15+
multi.exec = multi.EXEC = multi.exec_transaction;
16+
return multi;
17+
};
18+
19+
// ATTENTION: This is not a native function but is still handled as a individual command as it behaves just the same as multi
20+
RedisClient.prototype.batch = RedisClient.prototype.BATCH = function batch (args) {
21+
return new Multi(this, args);
22+
};
23+
24+
// Store db in this.select_db to restore it on reconnect
25+
RedisClient.prototype.select = RedisClient.prototype.SELECT = function select (db, callback) {
26+
var self = this;
27+
return this.send_command('select', [db], function (err, res) {
28+
if (err === null) {
29+
self.selected_db = db;
30+
}
31+
utils.callback_or_emit(self, callback, err, res);
32+
});
33+
};
34+
35+
// Store info in this.server_info after each call
36+
RedisClient.prototype.info = RedisClient.prototype.INFO = function info (callback) {
37+
var self = this;
38+
var ready = this.ready;
39+
this.ready = ready || this.offline_queue.length === 0; // keep the execution order intakt
40+
var tmp = this.send_command('info', [], function (err, res) {
41+
if (res) {
42+
var obj = {};
43+
var lines = res.toString().split('\r\n');
44+
var line, parts, sub_parts;
45+
46+
for (var i = 0; i < lines.length; i++) {
47+
parts = lines[i].split(':');
48+
if (parts[1]) {
49+
if (parts[0].indexOf('db') === 0) {
50+
sub_parts = parts[1].split(',');
51+
obj[parts[0]] = {};
52+
while (line = sub_parts.pop()) {
53+
line = line.split('=');
54+
obj[parts[0]][line[0]] = +line[1];
55+
}
56+
} else {
57+
obj[parts[0]] = parts[1];
58+
}
59+
}
60+
}
61+
obj.versions = [];
62+
/* istanbul ignore else: some redis servers do not send the version */
63+
if (obj.redis_version) {
64+
obj.redis_version.split('.').forEach(function (num) {
65+
obj.versions.push(+num);
66+
});
67+
}
68+
// Expose info key/vals to users
69+
self.server_info = obj;
70+
} else {
71+
self.server_info = {};
72+
}
73+
utils.callback_or_emit(self, callback, err, res);
74+
});
75+
this.ready = ready;
76+
return tmp;
77+
};
78+
79+
RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
80+
var self = this;
81+
var ready = this.ready;
82+
debug('Sending auth to ' + self.address + ' id ' + self.connection_id);
83+
84+
// Stash auth for connect and reconnect.
85+
this.auth_pass = pass;
86+
this.ready = this.offline_queue.length === 0; // keep the execution order intakt
87+
var tmp = this.send_command('auth', [pass], function (err, res) {
88+
if (err && no_password_is_set.test(err.message)) {
89+
self.warn('Warning: Redis server does not require a password, but a password was supplied.');
90+
err = null;
91+
res = 'OK';
92+
}
93+
94+
utils.callback_or_emit(self, callback, err, res);
95+
});
96+
this.ready = ready;
97+
return tmp;
98+
};
99+
100+
RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function hmset () {
101+
var arr,
102+
len = arguments.length,
103+
callback,
104+
i = 0;
105+
if (Array.isArray(arguments[0])) {
106+
arr = arguments[0];
107+
callback = arguments[1];
108+
} else if (Array.isArray(arguments[1])) {
109+
if (len === 3) {
110+
callback = arguments[2];
111+
}
112+
len = arguments[1].length;
113+
arr = new Array(len + 1);
114+
arr[0] = arguments[0];
115+
for (; i < len; i += 1) {
116+
arr[i + 1] = arguments[1][i];
117+
}
118+
} else if (typeof arguments[1] === 'object' && (arguments.length === 2 || arguments.length === 3 && typeof arguments[2] === 'function' || typeof arguments[2] === 'undefined')) {
119+
arr = [arguments[0]];
120+
for (var field in arguments[1]) { // jshint ignore: line
121+
arr.push(field, arguments[1][field]);
122+
}
123+
callback = arguments[2];
124+
} else {
125+
len = arguments.length;
126+
// The later should not be the average use case
127+
if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
128+
len--;
129+
callback = arguments[len];
130+
}
131+
arr = new Array(len);
132+
for (; i < len; i += 1) {
133+
arr[i] = arguments[i];
134+
}
135+
}
136+
return this.send_command('hmset', arr, callback);
137+
};

0 commit comments

Comments
 (0)