How do I ignore redis if it is not available?
Asked Answered
A

1

6

I want my application (lets say a simple node file for now) to work as it is even if redis is not available. I'm not able to do it the correct way. This is what I've tried.

var redis = require('redis');
var redisClient = null;

var getRedisClient = function(){
    if(redisClient){
        return redisClient;
    }

    try {
        redisClient = redis.createClient({connect_timeout : 5000, max_attempts : 1});
        redisClient.on("error", function(err) {
            console.error("Error connecting to redis", err);
            redisClient = null;
        });
        return redisClient;
    } catch(ex){
        console.log("error initialising redis client " + ex);
        return null;
    }
};

try {
    var client = getRedisClient();
    console.log("done!");
} catch (ex){
    console.log("Exception");
}

However, with this code my application exits if redis is not available (it shouldn't because i've not given a process.exit() command).

How can I solve this?

Abigael answered 6/3, 2015 at 2:36 Comment(5)
I think your application exits because there's nothing more for it to do. Add a server or something.Sunlit
@Farid no, if redis is on, the application doesn't exit.Abigael
When redis isn't on the application exists, because it has nothing to do. When redis is on, then there's a persistent connection to the redis server and application isn't exiting because the connection is not closed. Node will only close when there's no connections/servers/events or any other types of IO.Sunlit
so you're saying that this code is okay?Abigael
Looks fine to me, though you wouldn't know if the code is perfect or not till it's tested in production... :PSunlit
C
6

Checking for Successful Connection on Start

Using a promise, you could guarantee that at least initially, you were able to connect to redis without error within a specified time period:

const redis = require('redis');
const Promise = require('bluebird');

function getRedisClient(timeoutMs){
    return new Promise((resolve, reject) => {
        const redisClient = redis.createClient();
        const timer = setTimeout(() => reject('timeout'), timeoutMs);
        redisClient.on("ready", () => {
            clearTimeout(timer);
            resolve(redisClient);
        });
        redisClient.on("error", (err) => {
            clearTimeout(timer);
            reject(err);
        });
    });
};

const redisReadyTimeoutMs = 10000;

getRedisClient(redisReadyTimeoutMs)
    .then(redisClient => {
        // the client has connected to redis sucessfully
        return doSomethingUseful();
    }, error => {
        console.log("Unable to connect to redis", error);
    });

You Need Proper Error Handling

The redis client being non-null does NOT guarantee using it won't throw an error.

  • you could experience infrastructure misfortune e.g. crashed redis process, out of memory or network being down.

  • a bug in your code could cause an error e.g. invalid or missing arguments to a redis command.

You should be handling redis client errors as a matter of course.

DON'T null the Redis Client on Error

It won't give you much but it will force you to check for null every time you try and use it.

The redis client also has inbuilt reconnect and retry mechanisms that you'll miss out on if you null it after the first error. See the redis package docs, look for retry_strategy.

DO Wrap your redis client code with try .. catch ... or use .catch in your promise chain.

DO Make use of a retry_strategy.

Caucasus answered 10/4, 2017 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.