Search code examples
node.jsredispublish-subscribehapi.jsnode-redis

How to instantiate Multiple Redis Connections for Publish Subscribe (node.js + node_redis)


Scenario

Using node_redis to build a simple Redis Pubish Subscribe (chat) example: https://github.com/nelsonic/hapi-socketio-redis-chat-example (with Hapi.js and Socket.io)

We have created a node module redis_connection.js in our project ( see: http://git.io/vqaos ) to instantiate the Redis connection because we don't want to be repeating the code which connects (to RedisCloud) multiple times:

var redis = require('redis');
var url   = require('url');
var redisURL    = url.parse(process.env.REDISCLOUD_URL);
var redisClient = redis.createClient(redisURL.port, redisURL.hostname,
                  {no_ready_check: true});
redisClient.auth(redisURL.auth.split(":")[1]);

module.exports = redisClient;

Which we then use like this:

var redisClient = require('./redis_connection.js');

// Confirm we are able to connect to  RedisCloud:
redisClient.set('redis', 'working', redisClient.print);
redisClient.get('redis', function (err, reply) {
  console.log('RedisCLOUD is ' +reply.toString());
});

This works fine for normal GET/SET operations with Redis, but when we try to instantiate multiple connections to Redis (e.g: one to publish, another to subscribe and a third just to GET/SET keys/values) we get an error:

Issue

We are seeing the following error:

Error: Connection in subscriber mode, only subscriber commands may be used

What are we doing wrong?

Full code at the point where we see this issue: http://git.io/vqa6y

Note

We tried to dig through existing SO Q/A on this, e.g:

but did not find a solution that exactly matched our situation...

(any suggestions/help much appreciated!)


Solution

  • redis-connection node.js module

    In the interest of keeping this re-useable across our projects we wrote a (mini) node.js module to initialize Redis connections: https://github.com/dwyl/redis-connection

    Build Status Code Climate codecov.io Dependency Status devDependency Status

    The code is simple and tested and takes care of authentication if required. (not copy-pasting the module here to avoid duplication)
    see: https://github.com/dwyl/redis-connection/blob/master/index.js

    Usage:

    Install from NPM

    npm install redis-connection --save

    Use in your script

    var redisClient = require('redis-connection')();
    redisClient.set('hello', 'world');
    redisClient.get('hello', function (err, reply) {
      console.log('hello', reply.toString()); // hello world
    });
    

    Publish Subscribe

    var redisClient = require('redis-connection')(); // Publisher
    var redisSub = require('redis-connection')('subscriber');
    redisSub.subscribe("chat:messages:latest", "chat:people:new");
    

    For a working example see: https://github.com/dwyl/hapi-socketio-redis-chat-example

    The advantage is that we can re-use the same redisClient across multiple files in the same project without creating new connections (the single or pub/sub connection is cached and re-used)

    Credit: We borrowed ideas from several places so have up-voted all the answers. But ultimately we wrote a slightly different solution so we have shared it with everyone on NPM/GitHub. Thanks again everyone!