I am using the Redis NPM library for Node.js - I can listen for the connection 'ready' event like so
var client = require('redis').createClient();
client.on('ready', function () {
client.keys('*', function (err, keys) {
if (err) {
log.error(err);
} else {
for (var i = 0; i < keys.length; i++) {
createLocalDataMap(keys[i]);
}
}
});
});
however, how can I query Redis to see if it's ready instead of listening for an event that will probably fire before I am ready to handle it?
I suppose I could abandon the ready event and just do a query and then wait for a response, but is there a better, safer and more sophisticated way?
In other words, in all likelihood I will have to write a function like this:
var isReady = false;
client.on('ready', function(){
isReady = true;
});
function doSomethingMuchLater(){
if(isReady){
//query redis as normal
}
else {
client.on('ready', function(){
isReady = true;
//now I do what I wanted to do
});
}
}
this does not seem right at all, there must be a better way
The node-redis client automatically queues any commands you send before the connection is ready. Once it connects, those commands all get sent just before .on('ready') fires. As such, you really don't need to use .on('ready'). If you send commands too early, they'll still go through as expected, and if your connection fails entirely, they'll never be sent.
Even though the commands are queued, I got some nasty logging errors because I sending commands while the DB was not fully loaded. The connect event did not suffice.
From the docs:
[options.enableReadyCheck] boolean
When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server not respond to any commands. To work around this, when this option is true, ioredis will check the status of the Redis server, and when the Redis server is able to process commands, a ready event will be emitted.
So this is the only way I could make it reliably work is by using the ioredis library:
import Redis from 'ioredis';
class RedisClient {
private static instance: Redis.Redis | undefined;
private redisUrl: string;
private options?: Redis.RedisOptions;
private constructor(
redisUrl?: string,
options?: Redis.RedisOptions,
) {
this.redisUrl = redisUrl || `redis://${REDIS.HOST}:${REDIS.PORT}`;
this.options = options;
}
static async init(
redisUrl?: string,
options?: Redis.RedisOptions,
): Promise<RedisClient | undefined> {
try {
RedisClient.instance = new Redis(RedisClient.redisUrl, {
...options,
enableReadyCheck: true,
});
const onReady = (): Promise<boolean> => new Promise((resolve) => {
(RedisClient.instance as Redis.Redis).on('ready', () => {
resolve(true);
infoLogger.info('Redis server online...');
});
});
await onReady();
return new RedisClient(redisUrl, {
...options,
enableReadyCheck: true
});
} catch (err) {
new ServerError({
message: 'Redis client init error.',
internalCode: ErrorCodes.cacheInitError,
internal: true,
}).log();
if (RedisClient.instance) RedisClient.instance.quit();
return undefined;
}
}
async get(key: string): Promise<someType> {
...
}
async set<T extends Record<string, unknown>>(key: string, value: Stringified<T> | string): Promise<void> {
...
}
async del(key: string): Promise<void> {
...
}
async flush(): Promise<void> {
...
}
}
import RedisClient from 'somewhere';
const redis = await RedisClient.init();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With