7
votes

I have a valid server configuration in which redis can't be accessed, but the server can function correctly (I simply strip away features when redis can't be found).

However, I can't manage the connection errors well. I'd like to know when a connection error fails and shutdown the client in that case.

I've found that the connection retry will never stop. And quit() is actually swallowed - "Queueing quit for next server connection." - when called.

Is there a way to kill the client in the case where no connection can be established?

var redis = require("redis"),
    client = redis.createClient();

client.on("error", function(err) {
    logme.error("Bonk. The worker framework cannot connect to redis, which might be ok on a dev server!");
    logme.error("Resque error : "+err);
    client.quit();
});

client.on("idle", function(err) {
    logme.error("Redis queue is idle. Shutting down...");
});

client.on("end", function(err) {
    logme.error("Redis is shutting down. This might be ok if you chose not to run it in your dev environment");
});

client.on("ready", function(err) {
    logme.info("Redis up! Now connecting the worker queue client...");
});
  • ERROR - Resque error : Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
  • ERROR - Redis is shutting down. This might be ok if you chose not to run it in your dev environment
  • ERROR - Resque error : Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
  • ERROR - Resque error : Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
  • ERROR - Resque error : Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
  • ERROR - Resque error : Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED

One thing that is interesting is the fact that the 'end' event gets emitted. Why?

2

2 Answers

7
votes

The right way to have control on the client's reconnect behaviour is to use a retry_strategy.

Upon disconnection the redisClient will try to reconnect as per the default behaviour. The default behaviour can be overridden by providing a retry_strategy while creating the client.

Example usage of some fine grained control from the documentation.

var client = redis.createClient({
    retry_strategy: function (options) {
        if (options.error && options.error.code === 'ECONNREFUSED') {
            // End reconnecting on a specific error and flush all commands with
            // a individual error
            return new Error('The server refused the connection');
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
            // End reconnecting after a specific timeout and flush all commands
            // with a individual error
            return new Error('Retry time exhausted');
        }
        if (options.attempt > 10) {
            // End reconnecting with built in error
            return undefined;
        }
        // reconnect after
        return Math.min(options.attempt * 100, 3000);
    }
});

Ref: https://www.npmjs.com/package/redis#options-object-properties

For the purpose of killing the client when the connection is lost, we could use the following retry_strategy.

var client = redis.createClient({
    retry_strategy: function (options) {
        return undefined;
    }
});
1
votes

You might want to just forcibly end the connection to redis on error with client.end() rather than using client.quit() which waits for the completion of all outstanding requests and then sends the QUIT command which as you know requires a working connection with redis to complete.