miserylord
miserylord

Reputation: 365

Node.js Redis client get method error when Redis server is down

I am using node-redis version 3.0.2. However, I was checking how my website will respond if the Redis server is down. I have this request handler where It calls a function that checks first if the provided key is in Redis, else make a database call and then save the fetched data in Redis.

const GetByPriority = model => async (req, res) => {
    let { page=1, size=9 } = req.query;
    size = parseInt(size);
    page = parseInt(page);
    try {
        const doc = await SetOrGetCompanyCache(`companies-${page}-${size}`, async () => {
            const query = await model
                .find({})
                .limit(size*1)
                .skip((page-1)*size)
                .sort({ p: -1, _id:1 })
                .lean()
                .exec()
            return query;
        })
        if (!doc)
        {
            return res.status(404).end()
        }
        res.status(200).json({page:page, size:size, data: doc })
    } catch (e) {
        console.error(e)
        res.status(400).end()
    }
}

The problem is when the Redis server is down, there does not seem to be an error returned by redisClient's get method. I mean I don't get why it did not log the error. Also, It did not return InternalServerError.

export function SetOrGetCompanyCache (key, callback) {
    return new Promise((resolve, reject)=>{
        redisClient.get(key, async (error,data)=>{
            if(error)
            {
                console.log(error) //It does not get here
                return reject(createError.InternalServerError('Caching Error'))
            }
            //Cache hit
            if(data != null)
            {
                return resolve(JSON.parse(data))
            }
            //Cache miss
            //callback() --> MongoDB query
            const queryData = await callback();
            if(!queryData)
            {
                return reject(createError[404])
            }
            redisClient.setex(key,COMPANY_QUERY_EXP,JSON.stringify(queryData))
            resolve(queryData)
        })
    })
}

It only logged the following snippet

Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379

I believe this is because I added the following listener inside redisClient file

redisClient.on('error', (err)=>{
    console.error(err.message)
})

The problem now is that the set method does not return any error indicating that the Redis server is down, hence I can't even make the server perform a normal database call in that case.

Upvotes: 1

Views: 9149

Answers (1)

miserylord
miserylord

Reputation: 365

I asked the redis community on discord and they mentioned that I should set enable-offline-queue to false inside redis-client

It should look like this

export const redisClient  = createClient({
    port: process.env.REDIS_PORT,
    host: process.env.REDIS_HOST,
    //In order to turn off queuing commands and get an error if we couldn't connect to the redis server
    enable_offline_queue: false
});

As they mentioned

In Node Redis, if you handle add the on('error') stuff it will queue up your commands and then in the background try to reconnect. When it does reconnect, it will then run the queued commands. [7:30 PM] It actually follows a retry_strategy to attempt to reconnect. You can read all about it on the old README at https://www.npmjs.com/package/redis/v/3.1.2 npm redis A modern, high performance Redis client. Latest version: 4.0.4, last published: 24 days ago. Start using redis in your project by running npm i redis. There are 8235 other projects in the npm registry using redis.

[7:31 PM] You need to set the enable_offline_queue option to false to turn off this queueing and get an error.

Upvotes: 2

Related Questions