diff --git a/README.md b/README.md index f44e533e5b..31ceeabe47 100644 --- a/README.md +++ b/README.md @@ -171,12 +171,16 @@ port and host are probably fine. `options` in an object with the following poss * `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed. This may also be set to `javascript`. -* `return_buffers`: defaults to false. If set to `true`, then all replies will be sent to callbacks as node Buffer +* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer objects instead of JavaScript Strings. -* `detect_buffers`: default to false. If set to `true`, then replies will be sent to callbacks as node Buffer objects +* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects if any of the input arguments to the original command were Buffer objects. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. +* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the +Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the +cost of more latency. Most applications will want this set to `true`. + var redis = require("redis"), client = redis.createClient(null, null, {detect_buffers: true}); diff --git a/index.js b/index.js index 7ac120cde9..d5efbbc74d 100644 --- a/index.js +++ b/index.js @@ -33,6 +33,9 @@ function RedisClient(stream, options) { this.connected = false; this.ready = false; this.connections = 0; + if (this.options.socket_nodelay === undefined) { + this.options.socket_nodelay = true; + } this.should_buffer = false; this.command_queue_high_water = this.options.command_queue_high_water || 1000; this.command_queue_low_water = this.options.command_queue_low_water || 0; @@ -200,7 +203,9 @@ RedisClient.prototype.on_connect = function () { this.command_queue = new Queue(); this.emitted_end = false; this.initialize_retry_vars(); - this.stream.setNoDelay(); + if (this.options.socket_nodelay) { + this.stream.setNoDelay(); + } this.stream.setTimeout(0); this.init_parser(); diff --git a/test.js b/test.js index cd02160e7a..a02b36b1fc 100644 --- a/test.js +++ b/test.js @@ -70,7 +70,7 @@ function require_error(label) { }; } -function is_empty_array(obj) { +function is_empty_array(obj) { return Array.isArray(obj) && obj.length === 0; } @@ -396,6 +396,58 @@ tests.detect_buffers = function () { }); }; +tests.socket_nodelay = function () { + var name = "socket_nodelay", c1, c2, c3, ready_count = 0, quit_count = 0; + + c1 = redis.createClient(null, null, {socket_nodelay: true}); + c2 = redis.createClient(null, null, {socket_nodelay: false}); + c3 = redis.createClient(null, null); + + function quit_check() { + quit_count++; + + if (quit_count === 3) { + next(name); + } + } + + function run() { + assert.strictEqual(true, c1.options.socket_nodelay, name); + assert.strictEqual(false, c2.options.socket_nodelay, name); + assert.strictEqual(true, c3.options.socket_nodelay, name); + + c1.set(["set key 1", "set val"], require_string("OK", name)); + c1.set(["set key 2", "set val"], require_string("OK", name)); + c1.get(["set key 1"], require_string("set val", name)); + c1.get(["set key 2"], require_string("set val", name)); + + c2.set(["set key 3", "set val"], require_string("OK", name)); + c2.set(["set key 4", "set val"], require_string("OK", name)); + c2.get(["set key 3"], require_string("set val", name)); + c2.get(["set key 4"], require_string("set val", name)); + + c3.set(["set key 5", "set val"], require_string("OK", name)); + c3.set(["set key 6", "set val"], require_string("OK", name)); + c3.get(["set key 5"], require_string("set val", name)); + c3.get(["set key 6"], require_string("set val", name)); + + c1.quit(quit_check); + c2.quit(quit_check); + c3.quit(quit_check); + } + + function ready_check() { + ready_count++; + if (ready_count === 3) { + run(); + } + } + + c1.on("ready", ready_check); + c2.on("ready", ready_check); + c3.on("ready", ready_check); +}; + tests.reconnect = function () { var name = "reconnect"; @@ -734,7 +786,7 @@ tests.HGETALL_NULL = function () { }; tests.UTF8 = function () { - var name = "UTF8", + var name = "UTF8", utf8_sample = "ಠ_ಠ"; client.set(["utf8test", utf8_sample], require_string("OK", name)); @@ -859,7 +911,7 @@ tests.SDIFFSTORE = function () { client.sadd('baz', 'a', require_number(1, name)); client.sadd('baz', 'd', require_number(1, name)); - // NB: SDIFFSTORE returns the number of elements in the dstkey + // NB: SDIFFSTORE returns the number of elements in the dstkey client.sdiffstore('quux', 'foo', 'bar', 'baz', require_number(2, name));