Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the support of unix socket #642

Merged
merged 3 commits into from Aug 9, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 9 additions & 22 deletions README.md
Expand Up @@ -175,10 +175,15 @@ resume sending when you get `drain`.

`client` will emit `idle` when there are no outstanding commands that are awaiting a response.

## redis.createClient(port, host, options)
## redis.createClient()

Create a new client connection. `port` defaults to `6379` and `host` defaults
to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for
### overloading
* redis.createClient() = redis.createClient(6379, '127.0.0.1', {})
* redis.createClient(options) = redis.createClient(6379, '127.0.0.1', options)
* redis.createClient(unix_socket, options)
* redis.createClient(port, host, options)

If you have `redis-server` running on the same computer as node, then the defaults for
port and host are probably fine. `options` in an object with the following possible properties:

* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.
Expand Down Expand Up @@ -216,7 +221,7 @@ You can force an IPv6 if you set the family to 'IPv6'. See nodejs net or dns mod

```js
var redis = require("redis"),
client = redis.createClient(null, null, {detect_buffers: true});
client = redis.createClient({detect_buffers: true});

client.set("foo_rand000000000000", "OK");

Expand All @@ -234,24 +239,6 @@ You can force an IPv6 if you set the family to 'IPv6'. See nodejs net or dns mod

`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.

### Unix Domain Socket

You can also create a connection to Redis server via the unix domain socket if the server
has it enabled:

```js
var redis = require("redis");
var client = redis.createClient("/tmp/redis.sock");
```

Sample `redis.conf` configuration to enable unix domain socket listening:

```conf
unixsocket /tmp/redis.sock
unixsocketperm 755
```

See [issue #204](https://github.com/mranney/node_redis/issues/204) for more information.

## client.auth(password, callback)

Expand Down
80 changes: 58 additions & 22 deletions index.js
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -532,15 +532,15 @@ 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);
};

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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
};
Expand Down
46 changes: 38 additions & 8 deletions test.js
Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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";
Expand Down Expand Up @@ -610,11 +635,16 @@ tests.CLIENT_LIST = function() {
return next(name);
}

var pattern = /^add=/;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, typo here that breaks tests on older versions of Redis. I'll take care of this before I release.

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);
}));
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -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();
Expand Down