Reputation: 1588
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 }
Upvotes: 0
Views: 2105
Reputation: 5190
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.
Upvotes: 1