Skip to content

Commit e07575b

Browse files
committed
Support for multi and batch. Added tests.
1 parent bdf86be commit e07575b

File tree

4 files changed

+306
-15
lines changed

4 files changed

+306
-15
lines changed

index.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ function RedisClient (options, stream) {
159159
} else if (event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') {
160160
this.message_buffers = true;
161161
if (!this.using_buffer_parser) {
162-
this.using_buffer_parser = true;
163-
this.reply_parser = create_parser(this);
162+
this.switchToBufferParser();
164163
}
165164
}
166165
});
@@ -169,6 +168,11 @@ util.inherits(RedisClient, EventEmitter);
169168

170169
RedisClient.connection_id = 0;
171170

171+
RedisClient.prototype.switchToBufferParser = function() {
172+
this.using_buffer_parser = true;
173+
this.reply_parser = create_parser(this);
174+
}
175+
172176
function create_parser (self) {
173177
return Parser({
174178
returnReply: function (data) {
@@ -859,7 +863,7 @@ function handle_offline_command (self, command_obj) {
859863
}
860864

861865
RedisClient.prototype.internal_send_command_buf = function (command, args, callback, call_on_write) {
862-
this.internal_send_command(command, args, callback, call_on_write, true);
866+
return this.internal_send_command(command, args, callback, call_on_write, true);
863867
};
864868

865869
// Do not call internal_send_command directly, if you are not absolutly certain it handles everything properly
@@ -886,8 +890,7 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
886890
}
887891

888892
if (buffer_reply && !this.using_buffer_parser) {
889-
this.using_buffer_parser = true;
890-
this.reply_parser = create_parser(this);
893+
this.switchToBufferParser();
891894
}
892895

893896
for (i = 0; i < len; i += 1) {

lib/commands.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ commands.list.forEach(function (command) {
2323
if (!RedisClient.prototype['b_' + command]) {
2424
RedisClient.prototype['b_' + command] = function () {
2525
parseArgs(arguments);
26-
return this.internal_send_command(command, parseArgs_arr, parseArgs_callback, null, true);
26+
return this.internal_send_command(command, parseArgs_arr, parseArgs_callback, undefined, true);
2727
};
2828
}
2929

@@ -35,6 +35,15 @@ commands.list.forEach(function (command) {
3535
return this;
3636
};
3737
}
38+
39+
// Do not override existing functions
40+
if (!Multi.prototype['b_' + command]) {
41+
Multi.prototype['b_' + command] = function () {
42+
parseArgs(arguments);
43+
this.queue.push([command, parseArgs_arr, parseArgs_callback, undefined, true]);
44+
return this;
45+
};
46+
}
3847
});
3948

4049
function parseArgs(args) {

lib/multi.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ Multi.prototype.exec_transaction = function exec_transaction (callback) {
105105
var command_obj = self.queue.get(index);
106106
var command = command_obj[0];
107107
var cb = command_obj[2];
108-
var call_on_write = command_obj.length === 4 ? command_obj[3] : undefined;
108+
var call_on_write = command_obj.length >= 4 ? command_obj[3] : undefined;
109109
// Keep track of who wants buffer responses:
110-
if (self._client.options.return_buffers) {
111-
self.wants_buffers[index] = true;
112-
}else
113-
if (self._client.options.detect_buffers) {
114-
self.wants_buffers[index] = false;
110+
if (command_obj[4] && !self._client.using_buffer_parser) {
111+
self._client.switchToBufferParser();
112+
}
113+
self.wants_buffers[index] = self._client.options.return_buffers || command_obj[4];
114+
if (self._client.options.detect_buffers && !self.wants_buffers[index]) {
115115
for (var i = 0; i < command_obj[1].length; i += 1) {
116116
if (command_obj[1][i] instanceof Buffer) {
117117
self.wants_buffers[index] = true;
@@ -150,7 +150,8 @@ Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = funct
150150
self._client.cork();
151151
if (!callback) {
152152
while (command_obj = self.queue.shift()) {
153-
self._client.internal_send_command(command_obj[0], command_obj[1], command_obj[2], (command_obj.length === 4 ? command_obj[3] : undefined));
153+
console.log(command_obj[4]);
154+
self._client.internal_send_command(command_obj[0], command_obj[1], command_obj[2], (command_obj.length >= 4 ? command_obj[3] : undefined), command_obj[4]);
154155
}
155156
self._client.uncork();
156157
return !self._client.should_buffer;
@@ -179,7 +180,7 @@ Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = funct
179180
self.results = [];
180181
while (command_obj = self.queue.shift()) {
181182
var command = command_obj[0];
182-
var call_on_write = command_obj.length === 4 ? command_obj[3] : undefined;
183+
var call_on_write = command_obj.length >= 4 ? command_obj[3] : undefined;
183184
var cb;
184185
if (typeof command_obj[2] === 'function') {
185186
cb = batch_callback(self, command_obj[2], index);
@@ -189,7 +190,7 @@ Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = funct
189190
if (typeof callback === 'function' && index === len - 1) {
190191
cb = last_callback(cb);
191192
}
192-
this._client.internal_send_command(command, command_obj[1], cb, call_on_write);
193+
this._client.internal_send_command(command, command_obj[1], cb, call_on_write, command_obj[4]);
193194
index++;
194195
}
195196
self._client.uncork();

test/send_command_buf.spec.js

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
'use strict';
2+
3+
var assert = require('assert');
4+
var config = require('./lib/config');
5+
var helper = require('./helper');
6+
var redis = config.redis;
7+
8+
describe('send_command_buf', function () {
9+
10+
helper.allTests(function (parser, ip, basicArgs) {
11+
12+
[true, false].forEach(function(return_buffers) {
13+
oneType(parser, ip, basicArgs, basicArgs[2].detect_buffers, return_buffers);
14+
});
15+
});
16+
});
17+
18+
function oneType(parser, ip, basicArgs, detect_buffers, return_buffers) {
19+
if (detect_buffers && return_buffers) return;
20+
21+
describe('using ' + parser + ' and ' + ip + ' return_buffers: ' + return_buffers, function () {
22+
var client;
23+
var args = config.configureClient(parser, ip, {
24+
return_buffers: return_buffers,
25+
detect_buffers: detect_buffers
26+
});
27+
28+
beforeEach(function (done) {
29+
client = redis.createClient.apply(null, args);
30+
client.once('error', done);
31+
client.once('connect', function () {
32+
client.flushdb(function (err) {
33+
client.hmset('hash key 2', 'key 1', 'val 1', 'key 2', 'val 2');
34+
client.set('string key 1', 'string value');
35+
done(err);
36+
});
37+
});
38+
});
39+
40+
describe('get', function () {
41+
describe('first argument is a string', function () {
42+
it('returns a buffer', function (done) {
43+
client.b_get('string key 1', function (err, reply) {
44+
assert.strictEqual(true, Buffer.isBuffer(reply));
45+
assert.strictEqual('<Buffer 73 74 72 69 6e 67 20 76 61 6c 75 65>', reply.inspect());
46+
return done(err);
47+
});
48+
});
49+
50+
it('returns a buffer with send_command_buf', function (done) {
51+
client.send_command_buf('get', ['string key 1'], function (err, reply) {
52+
assert.strictEqual(true, Buffer.isBuffer(reply));
53+
assert.strictEqual('<Buffer 73 74 72 69 6e 67 20 76 61 6c 75 65>', reply.inspect());
54+
return done(err);
55+
});
56+
});
57+
58+
it('returns a buffer with internal_send_command_buf', function (done) {
59+
client.internal_send_command_buf('get', ['string key 1'], function (err, reply) {
60+
assert.strictEqual(true, Buffer.isBuffer(reply));
61+
assert.strictEqual('<Buffer 73 74 72 69 6e 67 20 76 61 6c 75 65>', reply.inspect());
62+
return done(err);
63+
});
64+
});
65+
66+
it('returns a bufffer when executed as part of transaction', function (done) {
67+
client.multi().b_get('string key 1').exec(function (err, reply) {
68+
assert.strictEqual(1, reply.length);
69+
assert.strictEqual(true, Buffer.isBuffer(reply[0]));
70+
assert.strictEqual('<Buffer 73 74 72 69 6e 67 20 76 61 6c 75 65>', reply[0].inspect());
71+
return done(err);
72+
});
73+
});
74+
});
75+
});
76+
77+
describe('multi.hget', function () {
78+
it('returns buffers', function (done) {
79+
client.multi()
80+
.b_hget('hash key 2', 'key 1')
81+
.b_hget('hash key 2', 'key 1')
82+
.b_hget('hash key 2', 'key 2')
83+
.b_hget('hash key 2', 'key 2')
84+
.exec(function (err, reply) {
85+
assert.strictEqual(true, Array.isArray(reply));
86+
assert.strictEqual(4, reply.length);
87+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect());
88+
assert.strictEqual(true, Buffer.isBuffer(reply[1]));
89+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[1].inspect());
90+
assert.strictEqual(true, Buffer.isBuffer(reply[2]));
91+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[2].inspect());
92+
assert.strictEqual(true, Buffer.isBuffer(reply[3]));
93+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[3].inspect());
94+
return done(err);
95+
});
96+
});
97+
});
98+
99+
describe('batch.hget', function () {
100+
it('returns buffers', function (done) {
101+
client.batch()
102+
.b_hget('hash key 2', 'key 1')
103+
.b_hget('hash key 2', 'key 1')
104+
.b_hget('hash key 2', 'key 2')
105+
.b_hget('hash key 2', 'key 2')
106+
.exec(function (err, reply) {
107+
assert.strictEqual(true, Array.isArray(reply));
108+
assert.strictEqual(4, reply.length);
109+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect());
110+
assert.strictEqual(true, Buffer.isBuffer(reply[1]));
111+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[1].inspect());
112+
assert.strictEqual(true, Buffer.isBuffer(reply[2]));
113+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[2].inspect());
114+
assert.strictEqual(true, Buffer.isBuffer(reply[3]));
115+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[3].inspect());
116+
return done(err);
117+
});
118+
});
119+
});
120+
121+
describe('hmget', function () {
122+
describe('using send_command_buf', function () {
123+
it('returns buffers for keys requested', function (done) {
124+
client.send_command_buf('hmget', ['hash key 2', 'key 1', 'key 2'], function (err, reply) {
125+
assert.strictEqual(true, Array.isArray(reply));
126+
assert.strictEqual(2, reply.length);
127+
assert.strictEqual(true, Buffer.isBuffer(reply[0]));
128+
assert.strictEqual(true, Buffer.isBuffer(reply[1]));
129+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect());
130+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[1].inspect());
131+
return done(err);
132+
});
133+
});
134+
135+
it('returns buffers for keys requested', function (done) {
136+
client.send_command('b_hmget', ['hash key 2', 'key 1', 'key 2'], function (err, reply) {
137+
assert.strictEqual(true, Array.isArray(reply));
138+
assert.strictEqual(2, reply.length);
139+
assert.strictEqual(true, Buffer.isBuffer(reply[0]));
140+
assert.strictEqual(true, Buffer.isBuffer(reply[1]));
141+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect());
142+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[1].inspect());
143+
return done(err);
144+
});
145+
});
146+
147+
if (!return_buffers) it('returns strings for keys requested', function (done) {
148+
client.send_command('hmget', ['hash key 2', 'key 1', 'key 2'], function (err, reply) {
149+
assert.strictEqual(true, Array.isArray(reply));
150+
assert.strictEqual(2, reply.length);
151+
assert.strictEqual('val 1', reply[0]);
152+
assert.strictEqual('val 2', reply[1]);
153+
return done(err);
154+
});
155+
});
156+
});
157+
158+
describe('using b_hmget', function () {
159+
it('handles array of strings with undefined values in transaction (repro #344)', function (done) {
160+
client.multi().b_hmget('hash key 2', 'key 3', 'key 4').exec(function (err, reply) {
161+
assert.strictEqual(true, Array.isArray(reply));
162+
assert.strictEqual(1, reply.length);
163+
assert.strictEqual(2, reply[0].length);
164+
assert.equal(null, reply[0][0]);
165+
assert.equal(null, reply[0][1]);
166+
return done(err);
167+
});
168+
});
169+
170+
it('returns buffers for keys requested', function (done) {
171+
client.b_hmget('hash key 2', 'key 1', 'key 2', function (err, reply) {
172+
assert.strictEqual(true, Array.isArray(reply));
173+
assert.strictEqual(2, reply.length);
174+
assert.strictEqual(true, Buffer.isBuffer(reply[0]));
175+
assert.strictEqual(true, Buffer.isBuffer(reply[1]));
176+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect());
177+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[1].inspect());
178+
return done(err);
179+
});
180+
});
181+
182+
if (!return_buffers) it('returns strings for keys requested', function (done) {
183+
client.hmget('hash key 2', 'key 1', 'key 2', function (err, reply) {
184+
assert.strictEqual(true, Array.isArray(reply));
185+
assert.strictEqual(2, reply.length);
186+
assert.strictEqual('val 1', reply[0]);
187+
assert.strictEqual('val 2', reply[1]);
188+
return done(err);
189+
});
190+
});
191+
192+
it('returns buffers for keys requested in transaction', function (done) {
193+
client.multi().b_hmget('hash key 2', 'key 1', 'key 2').exec(function (err, reply) {
194+
assert.strictEqual(true, Array.isArray(reply));
195+
assert.strictEqual(1, reply.length);
196+
assert.strictEqual(2, reply[0].length);
197+
assert.strictEqual(true, Buffer.isBuffer(reply[0][0]));
198+
assert.strictEqual(true, Buffer.isBuffer(reply[0][1]));
199+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0][0].inspect());
200+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[0][1].inspect());
201+
return done(err);
202+
});
203+
});
204+
205+
it('returns buffers for keys requested in .batch', function (done) {
206+
client.batch().b_hmget('hash key 2', 'key 1', 'key 2').exec(function (err, reply) {
207+
assert.strictEqual(true, Array.isArray(reply));
208+
assert.strictEqual(1, reply.length);
209+
assert.strictEqual(2, reply[0].length);
210+
assert.strictEqual(true, Buffer.isBuffer(reply[0][0]));
211+
assert.strictEqual(true, Buffer.isBuffer(reply[0][1]));
212+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0][0].inspect());
213+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[0][1].inspect());
214+
return done(err);
215+
});
216+
});
217+
});
218+
});
219+
220+
describe('hgetall', function (done) {
221+
describe('using send_command_buf', function (done) {
222+
it('returns buffer values', function (done) {
223+
client.send_command_buf('hgetall', ['hash key 2'], function (err, reply) {
224+
assert.strictEqual('object', typeof reply);
225+
assert.strictEqual(2, Object.keys(reply).length);
226+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply['key 1'].inspect());
227+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply['key 2'].inspect());
228+
return done(err);
229+
});
230+
});
231+
232+
it('returns buffer values', function (done) {
233+
client.send_command('b_hgetall', ['hash key 2'], function (err, reply) {
234+
assert.strictEqual('object', typeof reply);
235+
assert.strictEqual(2, Object.keys(reply).length);
236+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply['key 1'].inspect());
237+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply['key 2'].inspect());
238+
return done(err);
239+
});
240+
});
241+
});
242+
243+
describe('using b_hgetall', function (done) {
244+
it('returns buffer values', function (done) {
245+
client.b_hgetall('hash key 2', function (err, reply) {
246+
assert.strictEqual('object', typeof reply);
247+
assert.strictEqual(2, Object.keys(reply).length);
248+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply['key 1'].inspect());
249+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply['key 2'].inspect());
250+
return done(err);
251+
});
252+
});
253+
254+
it('returns buffer values when executed in transaction', function (done) {
255+
client.multi().b_hgetall('hash key 2').exec(function (err, reply) {
256+
assert.strictEqual(1, reply.length);
257+
assert.strictEqual('object', typeof reply[0]);
258+
assert.strictEqual(2, Object.keys(reply[0]).length);
259+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0]['key 1'].inspect());
260+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[0]['key 2'].inspect());
261+
return done(err);
262+
});
263+
});
264+
265+
it('returns buffer values when executed in .batch', function (done) {
266+
client.batch().b_hgetall('hash key 2').exec(function (err, reply) {
267+
assert.strictEqual(1, reply.length);
268+
assert.strictEqual('object', typeof reply[0]);
269+
assert.strictEqual(2, Object.keys(reply[0]).length);
270+
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0]['key 1'].inspect());
271+
assert.strictEqual('<Buffer 76 61 6c 20 32>', reply[0]['key 2'].inspect());
272+
return done(err);
273+
});
274+
});
275+
});
276+
});
277+
});
278+
}

0 commit comments

Comments
 (0)