1

I have an express database that connects to multiple redis servers by receiving the connection ip from a client.

It works fine if the redis database exists. The problem im facing is that if the ip doesnt exist, I will receive a

Error: Error: Redis connection to xxxx failed - connect ECONNREFUSED xxx

Being this totally understandable, but the problem is that my connection object is still defined. And i cant really seem how to identify this object as a failed connection. The only hint i might have might be in the connection._events.error variable, but it returns a [Function]

This is my code

let connections = []

const killRedis = (redisClient, ip, port) => {
    redisClient.quit()
    connections = connections.filter((i) => { return i.ip !== ip && i.port != port })
}

const subscribe = (redisClient, url, port) => {
    redisClient.on('error', function (err) {
        //this is supposed to handle the error, but i dont know how to make the "undefined" value available for the createRedisClient function. Since this seems to be delayed
        killRedis(redisClient, url, port)
        return undefined;
    });
    redisClient.on('connect', function () {
        console.log('Connected to Redis');
        return redisClient;
    });
}

findConnection = (ip, port) => {
    let connection = connections.filter(i => i.ip == ip && i.port == port)

    if (connection && connection.length > 0) {

        return connection[0].connection
    } else {
        connections.push({
            ip: ip,
            port: port,
            connection: require('redis').createClient(port, ip, {
                no_ready_check: true,
                db: 1
            })
        })
        let pushedConnection = connections.filter(i => i.ip == ip && i.port == port)[0].connection
        subscribe(pushedConnection, ip, port)
        return pushedConnection
    }
}
const createRedisClient = async (port, url) => {
    let redisClient = findConnection(url, port)
    console.log(redisClient._events.error) //[Function]
    return redisClient // this is always a connection object, even if the connection is faulty
}
module.exports = { createRedisClient }

1 Answer 1

2

Connection status is not known then findConnection returns, because node-redis is asynchronous, it uses callbacks. One solution would be to promisify your subscribe function, like this:

const subscribe = (redisClient, url, port) => new Promise((resolve, reject) => {
    redisClient.on('error', function (err) {
        console.log(err)
        killRedis(redisClient, url, port)
        reject(err)
    });
    redisClient.on('connect', function () {
        console.log('Connected to Redis');
        resolve(redisClient)
    });
})

Then, in the findConnection, you just handle the possible rejections with a try-catch block. Note that it's been marked async:

findConnection = async (ip, port) =>  {
    let connection = connections.filter(i => i.ip == ip && i.port == port)

    if (connection && connection.length > 0) {

        return connection[0].connection
    } else {
        connections.push({
            ip: ip,
            port: port,
            connection: require('redis').createClient(port, ip, {
                no_ready_check: true,
                db: 1
            })
        })
        let pushedConnection = connections.filter(i => i.ip == ip && i.port == port)[0].connection
        try {
            const client = await subscribe(pushedConnection, ip, port)
            return client
        } catch (error) {
            return undefined // not sure what you want to do with rejections
        }
    }

Then, finally (also async):

const createRedisClient = async (port, url) => {
    let redisClient = await findConnection(url, port)
    console.log(redisClient)
    return redisClient // this is undefined if there was an error connecting 
}

Instead of async-await, you could always use then-catch, etc. Also, I believe the error callback will be called on every error. That is, in case of a successful connection, if you encounter any redis errors later on, killRedis will still be called. If it's intended, alright. Otherwise, you may want to refactor your logic so that connections are only registered when they have successfully been made.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.