From 064260d1c5f2729f413e4266c3e1e0047cfd19ad Mon Sep 17 00:00:00 2001 From: Jack Tang Date: Thu, 7 Aug 2014 17:19:37 +0800 Subject: [PATCH] improve the interface to better support unix socket. delete client.host delete client.port add client.address add client.connectionOptions add tests.UNIX_SOCKET update all error message to use client.address update retry connection --- index.js | 80 ++++++++++++++++++++++++++++++++++++++++---------------- test.js | 46 ++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index 9674e7a..ed57003 100644 --- a/index.js +++ b/index.js @@ -178,7 +178,7 @@ RedisClient.prototype.flush_and_error = function (message) { }; RedisClient.prototype.on_error = function (msg) { - var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg; + var message = "Redis connection to " + this.address + " failed - " + msg; if (this.closing) { return; @@ -203,7 +203,7 @@ RedisClient.prototype.do_auth = function () { var self = this; if (exports.debug_mode) { - console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id); + console.log("Sending auth to " + self.address + " id " + self.connection_id); } self.send_anyway = true; self.send_command("auth", [this.auth_pass], function (err, res) { @@ -227,7 +227,7 @@ RedisClient.prototype.do_auth = function () { return self.emit("error", new Error("Auth failed: " + res.toString())); } if (exports.debug_mode) { - console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id); + console.log("Auth succeeded " + self.address + " id " + self.connection_id); } if (self.auth_callback) { self.auth_callback(err, res); @@ -249,7 +249,7 @@ RedisClient.prototype.do_auth = function () { RedisClient.prototype.on_connect = function () { if (exports.debug_mode) { - console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id); + console.log("Stream connected " + this.address + " id " + this.connection_id); } this.connected = true; @@ -532,7 +532,7 @@ RedisClient.prototype.connection_gone = function (why) { return; } - self.stream = net.createConnection(self.port, self.host); + self.stream = net.createConnection(self.connectionOption); self.install_stream_listeners(); self.retry_timer = null; }, this.retry_delay); @@ -540,7 +540,7 @@ RedisClient.prototype.connection_gone = function (why) { RedisClient.prototype.on_data = function (data) { if (exports.debug_mode) { - console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString()); + console.log("net read " + this.address + " id " + this.connection_id + ": " + data.toString()); } try { @@ -852,7 +852,7 @@ RedisClient.prototype.send_command = function (command, args, callback) { command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"; } if (exports.debug_mode) { - console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str); + console.log("send " + this.address + " id " + this.connection_id + ": " + command_str); } buffered_writes += !stream.write(command_str); } else { @@ -1213,28 +1213,64 @@ RedisClient.prototype.eval = RedisClient.prototype.EVAL = function () { }; -exports.createClient = function (port_arg, host_arg, options) { +exports.createClient = function(arg0, arg1, arg2){ + if( arguments.length === 0 ){ - var cnxFamily; - - if (options && options.family) { - cnxFamily = (options.family == 'IPv6' ? 6 : 4); - } - + // createClient() + return createClient_tcp(default_port, default_host, {}); + + } else if( typeof arg0 === 'number' || + typeof arg0 === 'string' && arg0.match(/^\d+$/) ){ + + // createClient( 3000, host, options) + // createClient('3000', host, options) + return createClient_tcp(arg0, arg1, arg2); + + } else if( typeof arg0 === 'string' ){ + + // createClient( '/tmp/redis.sock', options) + return createClient_unix(arg0,arg1); + + } else if( arg0 !== null && typeof arg0 === 'object' ){ + + // createClient(options) + return createClient_tcp(default_port, default_host, arg0 ); + + } else if( arg0 === null && arg1 === null ){ + + // for backward compatibility + // createClient(null,null,options) + return createClient_tcp(default_port, default_host, arg2); + + } else { + throw new Error('unknown type of connection in createClient()'); + } +} + +var createClient_unix = function(path, options){ var cnxOptions = { - 'port' : port_arg || default_port, - 'host' : host_arg || default_host, - 'family' : cnxFamily || '4' + path: path }; + var net_client = net.createConnection(cnxOptions); + var redis_client = new RedisClient(net_client, options || {}); - var redis_client, net_client; + redis_client.connectionOption = cnxOptions; + redis_client.address = path; - net_client = net.createConnection(cnxOptions); + return redis_client; +} - redis_client = new RedisClient(net_client, options); +var createClient_tcp = function (port_arg, host_arg, options) { + var cnxOptions = { + 'port' : port_arg || default_port, + 'host' : host_arg || default_host, + 'family' : (options && options.family === 'IPv6') ? 'IPv6' : 'IPv4' + }; + var net_client = net.createConnection(cnxOptions); + var redis_client = new RedisClient(net_client, options || {}); - redis_client.port = cnxOptions.port; - redis_client.host = cnxOptions.host; + redis_client.connectionOption = cnxOptions; + redis_client.address = cnxOptions.host + ':' + cnxOptions.port; return redis_client; }; diff --git a/test.js b/test.js index b9d9155..be29abd 100644 --- a/test.js +++ b/test.js @@ -119,7 +119,7 @@ tests.IPV4 = function () { var ipv4Client = redis.createClient( PORT, "127.0.0.1", { "family" : "IPv4" } ); ipv4Client.once("ready", function start_tests() { - console.log("Connected to " + ipv4Client.host + ":" + ipv4Client.port + ", Redis server version " + ipv4Client.server_info.redis_version + "\n"); + console.log("Connected to " + ipv4Client.address + ", Redis server version " + ipv4Client.server_info.redis_version + "\n"); console.log("Using reply parser " + ipv4Client.reply_parser.name); ipv4Client.quit(); @@ -141,7 +141,7 @@ tests.IPV6 = function () { var ipv6Client = redis.createClient( PORT, "::1", { "family" : "IPv6" } ); ipv6Client.once("ready", function start_tests() { - console.log("Connected to " + ipv6Client.host + ":" + ipv6Client.port + ", Redis server version " + ipv6Client.server_info.redis_version + "\n"); + console.log("Connected to " + ipv6Client.address + ", Redis server version " + ipv6Client.server_info.redis_version + "\n"); console.log("Using reply parser " + ipv6Client.reply_parser.name); ipv6Client.quit(); @@ -159,6 +159,31 @@ tests.IPV6 = function () { }); } +tests.UNIX_SOCKET = function () { + var unixClient = redis.createClient('/tmp/redis.sock'); + + // if this fails, check the permission of unix socket. + // unixsocket /tmp/redis.sock + // unixsocketperm 777 + + unixClient.once('ready', function start_tests(){ + console.log("Connected to " + unixClient.address + ", Redis server version " + unixClient.server_info.redis_version + "\n"); + console.log("Using reply parser " + unixClient.reply_parser.name); + + unixClient.quit(); + run_next_test(); + }); + + unixClient.on( 'end', function(){ + + }); + + // Exit immediately on connection failure, which triggers "exit", below, which fails the test + unixClient.on("error", function (err) { + console.error("client: " + err.stack); + process.exit(); + }); +} tests.FLUSHDB = function () { var name = "FLUSHDB"; @@ -610,11 +635,16 @@ tests.CLIENT_LIST = function() { return next(name); } + var pattern = /^add=/; + if ( server_version_at_least(client, [2, 8, 12])) { + pattern = /^id=\d+ addr=/; + } + function checkResult(result) { var lines = result.toString().split('\n').slice(0, -1); assert.strictEqual(lines.length, 4); assert(lines.every(function(line) { - return line.match(/^addr=/); + return line.match(pattern); })); } @@ -683,7 +713,7 @@ tests.WATCH_TRANSACTION = function () { tests.detect_buffers = function () { - var name = "detect_buffers", detect_client = redis.createClient(null, null, {detect_buffers: true}); + var name = "detect_buffers", detect_client = redis.createClient({detect_buffers: true}); detect_client.on("ready", function () { // single Buffer or String @@ -750,9 +780,9 @@ 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); + c1 = redis.createClient({socket_nodelay: true}); + c2 = redis.createClient({socket_nodelay: false}); + c3 = redis.createClient(); function quit_check() { quit_count++; @@ -2194,7 +2224,7 @@ run_next_test = function run_next_test() { }; client.once("ready", function start_tests() { - console.log("Connected to " + client.host + ":" + client.port + ", Redis server version " + client.server_info.redis_version + "\n"); + console.log("Connected to " + client.address + ", Redis server version " + client.server_info.redis_version + "\n"); console.log("Using reply parser " + client.reply_parser.name); run_next_test();