Skip to content

Commit ed2fc95

Browse files
author
Ruben Bridgewater
committed
Fix should_buffer return values and empty .batch and .auth return value being sync
Fix test
1 parent 7d2bb8e commit ed2fc95

File tree

6 files changed

+57
-21
lines changed

6 files changed

+57
-21
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,13 @@ So please attach the error listener to node_redis.
152152
### "drain"
153153

154154
`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
155-
writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,
156-
you need to check `client.command_queue.length` to decide when to reduce your send rate and resume sending commands when you get `drain`.
155+
writable. This event can be used to stream commands in to Redis and adapt to backpressure.
156+
157+
All commands return a boolean if the stream had to buffer or not. If false is returned the stream had to buffer.
158+
That way you can decide when to reduce your send rate and resume sending commands when you get `drain`.
159+
160+
You can manually control the low water and high water marks by passing ommand_queue_high_water` and `command_queue_low_water` to the client options.
161+
Check the [Node.js streams API](https://nodejs.org/api/stream.html) for further info.
157162

158163
### "idle"
159164

@@ -689,7 +694,7 @@ Client count: 5, node version: 4.1.2, server version: 3.0.3, parser: hiredis
689694
End of tests. Total time elapsed: 44952 ms
690695

691696
The hiredis and js parser should most of the time be on the same level. The js parser lacks speed for large responses though.
692-
Therefor the hiredis parser is the default used in node_redis. To use `hiredis`, do:
697+
Therefor the hiredis parser is the default used in node_redis and we recommend using the hiredis parser. To use `hiredis`, do:
693698

694699
npm install hiredis redis
695700

changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Features
1919
Bugfixes
2020

2121
- Fix a javascript parser regression introduced in 2.0 that could result in timeouts on high load. ([@BridgeAR](https://github.com/BridgeAR))
22-
- Fixed should_buffer boolean for .exec, .select and .auth commands not being returned ([@BridgeAR](https://github.com/BridgeAR))
22+
- Fixed should_buffer boolean for .exec, .select and .auth commands not being returned and fix a couple special conditions ([@BridgeAR](https://github.com/BridgeAR))
2323

2424
If you do not rely on transactions but want to reduce the RTT you can use .batch from now on. It'll behave just the same as .multi but it does not have any transaction and therefor won't roll back any failed commands.<br>
2525
Both .multi and .batch are from now on going to cache the commands and release them while calling .exec.

index.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,8 @@ RedisClient.prototype.send_command = function (command, args, callback) {
690690
} else {
691691
this.emit('error', err);
692692
}
693-
return false;
693+
// Singal no buffering
694+
return true;
694695
}
695696
}
696697

@@ -725,7 +726,7 @@ RedisClient.prototype.send_command = function (command, args, callback) {
725726
this.offline_queue.push(command_obj);
726727
this.should_buffer = true;
727728
}
728-
// Return false to signal no buffering
729+
// Return false to signal buffering
729730
return false;
730731
}
731732

@@ -739,7 +740,7 @@ RedisClient.prototype.send_command = function (command, args, callback) {
739740
err = new Error('Connection in subscriber mode, only subscriber commands may be used');
740741
err.command = command.toUpperCase();
741742
this.emit('error', err);
742-
return false;
743+
return true;
743744
}
744745
this.command_queue.push(command_obj);
745746
this.commands_sent += 1;
@@ -800,7 +801,7 @@ RedisClient.prototype.writeStream = function (data) {
800801

801802
// Do not use a pipeline
802803
if (this.pipeline === 0) {
803-
return !this.stream.__write(data);
804+
return this.stream.__write(data);
804805
}
805806
this.pipeline--;
806807
this.pipeline_queue.push(data);
@@ -975,11 +976,13 @@ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function (pass, callba
975976
var err = new Error('The password has to be of type "string"');
976977
err.command = 'AUTH';
977978
if (callback) {
978-
callback(err);
979+
setImmediate(function () {
980+
callback(err);
981+
});
979982
} else {
980983
this.emit('error', err);
981984
}
982-
return false;
985+
return true;
983986
}
984987
this.auth_pass = pass;
985988
debug('Saving auth as ' + this.auth_pass);
@@ -988,7 +991,7 @@ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function (pass, callba
988991
return this.send_command('auth', [this.auth_pass], callback);
989992
}
990993
this.auth_callback = callback;
991-
return false;
994+
return true;
992995
};
993996

994997
RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function (key, args, callback) {
@@ -1180,9 +1183,11 @@ Multi.prototype.exec = Multi.prototype.EXEC = function (callback) {
11801183
var args;
11811184
if (len === 0) {
11821185
if (callback) {
1183-
callback(null, []);
1186+
setImmediate(function () {
1187+
callback(null, []);
1188+
});
11841189
}
1185-
return false;
1190+
return true;
11861191
}
11871192
this.results = new Array(len);
11881193
this._client.pipeline = len;

test/auth.spec.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,15 @@ describe("client authentication", function () {
128128
if (helper.redisProcess().spawnFailed()) this.skip();
129129

130130
client = redis.createClient.apply(redis.createClient, args);
131+
var async = true;
131132
client.auth(undefined, function(err, res) {
132133
assert.strictEqual(err.message, 'The password has to be of type "string"');
133134
assert.strictEqual(err.command, 'AUTH');
134135
assert.strictEqual(res, undefined);
136+
async = false;
135137
done();
136138
});
139+
assert(async);
137140
});
138141

139142
it('should emit an error if the password is not of type string and no callback has been provided', function (done) {

test/commands/batch.spec.js renamed to test/batch.spec.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

33
var assert = require('assert');
4-
var config = require("../lib/config");
5-
var helper = require('../helper');
4+
var config = require("./lib/config");
5+
var helper = require('./helper');
66
var redis = config.redis;
77
var uuid = require('uuid');
88

@@ -52,7 +52,7 @@ describe("The 'batch' method", function () {
5252

5353
beforeEach(function (done) {
5454
client = redis.createClient.apply(redis.createClient, args);
55-
client.once("connect", function () {
55+
client.once("ready", function () {
5656
client.flushdb(function (err) {
5757
return done(err);
5858
});
@@ -63,6 +63,19 @@ describe("The 'batch' method", function () {
6363
client.end();
6464
});
6565

66+
it("returns an empty result array", function (done) {
67+
var batch = client.batch();
68+
var async = true;
69+
var notBuffering = batch.exec(function (err, res) {
70+
assert.strictEqual(err, null);
71+
assert.strictEqual(res.length, 0);
72+
async = false;
73+
done();
74+
});
75+
assert(async);
76+
assert.strictEqual(notBuffering, true);
77+
});
78+
6679
it('fail individually when one command fails using chaining notation', function (done) {
6780
var batch1, batch2;
6881
batch1 = client.batch();
@@ -216,8 +229,7 @@ describe("The 'batch' method", function () {
216229

217230
it('runs a batch without any further commands and without callback', function() {
218231
var buffering = client.batch().exec();
219-
assert(typeof buffering === 'boolean');
220-
assert(!buffering);
232+
assert.strictEqual(buffering, true);
221233
});
222234

223235
it('allows batchple operations to be performed using a chaining API', function (done) {

test/commands/multi.spec.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ describe("The 'multi' method", function () {
3232
});
3333

3434
it("reports an error", function (done) {
35-
client.multi();
36-
client.exec(function (err, res) {
35+
var multi = client.multi();
36+
var notBuffering = multi.exec(function (err, res) {
3737
assert(err.message.match(/The connection has already been closed/));
3838
done();
3939
});
40+
assert.strictEqual(notBuffering, false);
4041
});
4142

4243
it("reports an error if promisified", function () {
@@ -51,7 +52,7 @@ describe("The 'multi' method", function () {
5152

5253
beforeEach(function (done) {
5354
client = redis.createClient.apply(redis.createClient, args);
54-
client.once("connect", function () {
55+
client.once("ready", function () {
5556
client.flushdb(function (err) {
5657
return done(err);
5758
});
@@ -62,6 +63,16 @@ describe("The 'multi' method", function () {
6263
client.end();
6364
});
6465

66+
it("returns an empty result array", function (done) {
67+
var multi = client.multi();
68+
var notBuffering = multi.exec(function (err, res) {
69+
assert.strictEqual(err, null);
70+
assert.strictEqual(res.length, 0);
71+
done();
72+
});
73+
assert.strictEqual(notBuffering, true);
74+
});
75+
6576
it('roles back a transaction when one command in a sequence of commands fails', function (done) {
6677
var multi1, multi2;
6778
var expected = helper.serverVersionAtLeast(client, [2, 6, 5]) ? helper.isError() : function () {};

0 commit comments

Comments
 (0)