Search code examples
javascriptnode.jssocket.iosocket.io-redisredis-server

redis-server offline crashes node


I am having one heck of a time here. I have read through so much documentation, and other peoples questions regarding the same topic and cannot find an answer on how to stop this from happening. I am purposely shutting down the redis server to try to make sure the application will not completely go nuclear while in production, but nothing I do seems to stop that from happening. Here is a very simple example of what my code is right now...

var cluster = require('cluster');
var express = require('express');
var http = require('http');
var redis = require('redis');
var redisAdapter = require('socket.io-redis');
var sticky = require('sticky-session');
var port = process.env.PORT || 3333;
var workers = 3;
var app = express();
var server = http.createServer(app);
var io = require('socket.io')(server);

if(!sticky.listen(server, 3333, {workers: workers})) {
    server.once('listening', () => {
        console.log('server started on port ' + port);
        process.on('exit', () => {
            io.emit('error', {errorType: 'SERVER_SHUTDOWN'});
        });
        process.on('uncaughtException', (err) => {
            console.log('uncaught exception occurred');
            console.log(err);
        });
    });
} else {
    addRedisAdapter(io);
    addIOEventHandler(io);
}

function addRedisAdapter(io) {
    var redisUrl = process.env.REDISTOGO_URL || 'redis://127.0.0.1:6379';
    var redisOptions = require('parse-redis-url')(redis).parse(redisUrl);
    var pub = redis.createClient(redisOptions.port, redisOptions.host, { returnBuffers: true});
    var sub = redis.createClient(redisOptions.port, redisOptions.host, {returnBuffers: true});
    io.on('error', (err) => {
        console.log(err);
    });
    io.on('uncaughtException', (err) => {
        console.log(err);
    });
    io.adapter(redisAdapter({pubClient: pub, subClient: sub}));
    console.log('redis adapter started');
}
function addIOEventHandler(io) {
    //all the events for io
}

Now, I start redis-server, then I start node.js with this server. Then I bring up a terminal window and type in "redis-cli shutdown" to force the redis server to go offline. as soon as I do that the node.js terminal window goes nuts looping through the same error over and over.

events.js:154
  throw er; // Unhandled 'error' event
  ^

Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
    at Object.exports._errnoException (util.js:893:11)
    at exports._exceptionWithHostPort (util.js:916:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1075:14)
redis adapter started with url: redis://127.0.0.1:6379

I have both process.on('uncaughtException' ... and io.on('uncaughtException' ... as well as an io.on('error', ... handler, yet every time the server just sits there looping saying there is an "Unhandled 'error' event" Can someone please help me out here. I don't see how this can possibly be unhandled error, it doesn't make sense in my mind for some reason. Thank you in advance for any possible help you can give. I have been going on the interwebs for hours trying to find any other possible option and they all say the same thing, use io.on('error', or io.on('uncaughtException', or process.on('uncaughtException', I have them all and it still errors out and crashes node.


Solution

  • Thanks to @SadiRubaiyet for pointing me in the right direction. I had to add an error event to both pub and sub. Once I did that, no more node crash when redis goes down. Here is the edited code...

    var cluster = require('cluster');
    var express = require('express');
    var http = require('http');
    var redis = require('redis');
    var redisAdapter = require('socket.io-redis');
    var sticky = require('sticky-session');
    var port = process.env.PORT || 3333;
    var workers = 3;
    var app = express();
    var server = http.createServer(app);
    var io = require('socket.io')(server);
    
    if(!sticky.listen(server, 3333, {workers: workers})) {
        server.once('listening', () => {
            console.log('server started on port ' + port);
            process.on('exit', () => {
                io.emit('error', {errorType: 'SERVER_SHUTDOWN'});
            });
            process.on('uncaughtException', (err) => {
                console.log('uncaught exception occurred');
                console.log(err);
            });
        });
    } else {
        addRedisAdapter(io);
        addIOEventHandler(io);
    }
    
    function addRedisAdapter(io) {
        var redisUrl = process.env.REDISTOGO_URL || 'redis://127.0.0.1:6379';
        var redisOptions = require('parse-redis-url')(redis).parse(redisUrl);
        var pub = redis.createClient(redisOptions.port, redisOptions.host, { returnBuffers: true});
        var sub = redis.createClient(redisOptions.port, redisOptions.host, {returnBuffers: true});
        io.on('error', (err) => {
            console.log(err);
        });
        io.on('uncaughtException', (err) => {
            console.log(err);
        });
        /*HERE IS THE NEW CODE THAT MADE IT WORK*/
        pub.on('error', (err) => {
            console.log('error from pub');
            console.log(err);
        });
        sub.on('error', (err) => {
            console.log('error from sub);
            console.log(err);
        });
        /*END*/
        io.adapter(redisAdapter({pubClient: pub, subClient: sub}));
        console.log('redis adapter started');
    }
    function addIOEventHandler(io) {
        //all the events for io
    }