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

0.9 RedisStore UNIX Domain Sockets (using Redis 0.8.2) #1169

Closed
runspired opened this issue Feb 22, 2013 · 2 comments
Closed

0.9 RedisStore UNIX Domain Sockets (using Redis 0.8.2) #1169

runspired opened this issue Feb 22, 2013 · 2 comments

Comments

@runspired
Copy link

For threaded instances of Node running on the same machine it makes more sense to use a Unix Domain Socket (UDS) than to use TCP. Redis supports UDS via redis.createClient( filepath_for_unix_socket );. Unfortunately, RedisStore relies on defined host and port parameters. Unfortunately, the following method from the documentation doing the following leads to an EADDRINUSE error for both TCP and UNIX sockets:

var RedisStore = require('socket.io/lib/stores/redis')
  , redis  = require('socket.io/node_modules/redis')
  , pub    = redis.createClient( filepath_for_unix_socket )
  , sub    = redis.createClient( filepath_for_unix_socket )
  , client = redis.createClient( filepath_for_unix_socket );

io.set('store', new RedisStore({
  redisPub : pub
, redisSub : sub
, redisClient : client
}));

For TCP the following works.

//store socket.io info in redisStore instead
var RedisStore          =   require('socket.io/lib/stores/redis')
    ,   redis                   =   require('redis')
    ,   opts                    =   { host : 'localhost' , port : 6379 };

//setup io storage
io.set('store', new RedisStore({
      redisPub : opts
    , redisSub : opts
    , redisClient : opts
}));

But this does not

,    opts              =    filepath_for_unix_socket;

Nor do (unsurprisingly) any of these attempted workarounds

,    opts              =    { host : filepath_for_unix_socket, port : false };
,    opts              =    { host : false, port : filepath_for_unix_socket };
,    opts              =    { host : filepath_for_unix_socket, port : '' };
,    opts              =    { host : '', port : filepath_for_unix_socket };
,    opts              =    { host : filepath_for_unix_socket };
,    opts              =    { port : filepath_for_unix_socket };

@guille has stated he is drastically changing RedisStore in 1.0, #862 (comment)

Hopefully this will allow for UDS use, but until then if you find yourself wanting to use one, you'll need to modify this code within branch 0.9 lib/stores/redis.js to add support.

// initialize a pubsub client and a regular client
if (opts.redisPub instanceof RedisClient) {
  this.pub = opts.redisPub;
} else {
  opts.redisPub || (opts.redisPub = {});
  this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
}
if (opts.redisSub instanceof RedisClient) {
  this.sub = opts.redisSub;
} else {
  opts.redisSub || (opts.redisSub = {});
  this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
}
if (opts.redisClient instanceof RedisClient) {
  this.cmd = opts.redisClient;
} else {
  opts.redisClient || (opts.redisClient = {});
  this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host,  opts.redisClient);
}

To look something like this

  // initialize a pubsub client and a regular client
  if (opts.redisPub instanceof RedisClient) {
    this.pub = opts.redisPub;
  } else {
    opts.redisPub || (opts.redisPub = {});
    if( Object.prototype.toString.call( opts.redisPub ) == '[object String]' )
        this.pub = redis.createClient( opts.redisPub );
    else
        this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
  }
  if (opts.redisSub instanceof RedisClient) {
    this.sub = opts.redisSub;
  } else {
    opts.redisSub || (opts.redisSub = {});
    if( Object.prototype.toString.call( opts.redisSub ) == '[object String]' )
        this.sub = redis.createClient( opts.redisSub );
    else
        this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
  }
  if (opts.redisClient instanceof RedisClient) {
    this.cmd = opts.redisClient;
  } else {
    opts.redisClient || (opts.redisClient = {});
    if( Object.prototype.toString.call( opts.redisClient ) == '[object String]' )
        this.cmd = redis.createClient( opts.redisClient );
    else
        this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
  }
@3rd-Eden
Copy link
Contributor

You can just supply the redis store with your own redis instances. No need to supply it with options

Sent from my iPhone

On Feb 22, 2013, at 7:06 PM, James Thoburn notifications@github.com wrote:

For threaded instances of Node running on the same machine it makes more sense to use a Unix Domain Socket (UDS) than to use TCP. Redis supports UDS via redis.createClient( filepath_for_unix_socket );. Unfortunately, RedisStore relies on defined host and port parameters. Unfortunately, the following method from the documentation doing the following leads to an EADDRINUSE error for both TCP and UNIX sockets:

var RedisStore = require('socket.io/lib/stores/redis')
, redis = require('socket.io/node_modules/redis')
, pub = redis.createClient( filepath_for_unix_socket )
, sub = redis.createClient( filepath_for_unix_socket )
, client = redis.createClient( filepath_for_unix_socket );

io.set('store', new RedisStore({
redisPub : pub
, redisSub : sub
, redisClient : client
}));
For TCP the following works.

//store socket.io info in redisStore instead
var RedisStore = require('socket.io/lib/stores/redis')
, redis = require('redis')
, opts = { host : 'localhost' , port : 6379 };

//setup io storage
io.set('store', new RedisStore({
redisPub : opts
, redisSub : opts
, redisClient : opts
}));
But this does not

, opts = filepath_for_unix_socket;
Nor do (unsurprisingly) any of these attempted workarounds

, opts = { host : filepath_for_unix_socket, port : false };
, opts = { host : false, port : filepath_for_unix_socket };
, opts = { host : filepath_for_unix_socket, port : '' };
, opts = { host : '', port : filepath_for_unix_socket };
, opts = { host : filepath_for_unix_socket };
, opts = { port : filepath_for_unix_socket };
@guille has stated he is drastically changing RedisStore in 1.0, #862

Hopefully this will allow for UDS use, but until then if you find yourself wanting to use one, you'll need to modify this code within branch 0.9 lib/stores/redis.js to add support.

// initialize a pubsub client and a regular client
if (opts.redisPub instanceof RedisClient) {
this.pub = opts.redisPub;
} else {
opts.redisPub || (opts.redisPub = {});
this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
}
if (opts.redisSub instanceof RedisClient) {
this.sub = opts.redisSub;
} else {
opts.redisSub || (opts.redisSub = {});
this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
}
if (opts.redisClient instanceof RedisClient) {
this.cmd = opts.redisClient;
} else {
opts.redisClient || (opts.redisClient = {});
this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
}
To look something like this

// initialize a pubsub client and a regular client
if (opts.redisPub instanceof RedisClient) {
this.pub = opts.redisPub;
} else {
opts.redisPub || (opts.redisPub = {});
if( Object.prototype.toString.call( opts.redisPub ) == '[object String]' )
this.pub = redis.createClient( opts.redisPub );
else
this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
}
if (opts.redisSub instanceof RedisClient) {
this.sub = opts.redisSub;
} else {
opts.redisSub || (opts.redisSub = {});
if( Object.prototype.toString.call( opts.redisSub ) == '[object String]' )
this.sub = redis.createClient( opts.redisSub );
else
this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
}
if (opts.redisClient instanceof RedisClient) {
this.cmd = opts.redisClient;
} else {
opts.redisClient || (opts.redisClient = {});
if( Object.prototype.toString.call( opts.redisClient ) == '[object String]' )
this.cmd = redis.createClient( opts.redisClient );
else
this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
}

Reply to this email directly or view it on GitHub.

@runspired
Copy link
Author

You can't actually, at least not with the version of socket.io I'm running (0.9.13). As I stated above, passing an instance instead of an object results in an EADDRINUSE error for every attempted redis.createClient() call after the first call. This error is independent of the whether filepath_to_unix_socket or a host:port is used. When using cluster net.createConnection() is supposed to be sent to the master instance of Node but for some reason this isn't happening here. Looking at the code the redis binding, I'm really not sure why one works and one doesn't.

_EDIT_
@3rd-Eden Actually the culprit for that EADDRINUSE might have been with the default redis configuration and not with the way the clients were created. Only change between when I first setup socket.io to use redis and now is writing my own redis.config and messing with file ownership, now sending in client's that I've created works. Huh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants