skip to Main Content

I’m implementing a cache mechanism on my app using redis. I’m using redis ^4.0.2.

My app is organized like this:

 - index.js
 -- routes
    -- users.js
 -- controllers
    -- users.js
 -- models
    -- user.js
 -- db
    -- postgres.js
    -- redis.js

I would like to implement the cache at the models but I want to create the redis connection in db/redis.js and export it and have the model requiring it.

This is what db/redis.js looks like:

const Redis = require('redis');
const redisClient = Redis.createClient();

redisClient.connect();

redisClient.on('connect', function() {
  console.log('Redis is Connected!');
});

redisClient.on('error', err => {
  console.log('Redis Error ' + err);
});

redisClient.on('end', () => {
  console.log('Redis disconnected');
});
redisClient.on('reconnecting', () => {
  console.log('Redis reconnecting');
});

module.exports = redisClient;

This is my model:

const postgresClient = require('../db/postgres');
const redisClient = require('../db/redis');

const getAllUsers = (params, callback) => {
   console.log('getAllUsers');
   const page = params.page || 1;
   const count = params.count || 5;
   const offset = (page - 1) * count;
   const queryStr = `SELECT * FROM users OFFSET ${offset} FETCH NEXT ${count} ROWS ONLY`;
   const cacheKey = `users?page=${page}&count=${count}`;

   redisClient.get(cacheKey, (error, users) => {
      console.log('redisClient.get');
      if (error) callback(error);
      if (users != null) {
         console.log('sending data from cache')  
         callback(null, JSON.parse(users));
      } else {
         postgresClient.query(queryStr, (err, res) => { 
            console.log('querying db and setting cache')
            if (err) callback(err);
            redisClient.setex(cacheKey, DEFAULT_EXPIRATION, JSON.stringify(res.rows))
            callback(null, res.rows);
         })
      }
   }
}

When I run the server and make a request to the endpoint that uses this model, the console.log('getAllUsers'); runs but console.log('redisClient.get'); doesn’t.

It seems like the redis client get callback never executes and I wonder why.

Any help or advice is welcome. Thanks in advance.

2

Answers


  1. It looks to me as if you’re reinventing the world. If what you want is just a cache, have you considered using a package for that? I’ve had good luck with this one:

    https://www.npmjs.com/package/cacheman-redis

    If that doesn’t work for you, it looks like the latest version of the redis npm recommends using promises, like so:

    const value = await redisClient.get(`key`);
    if (!value) {
      // query postgres and set the value.  
    }
    

    If you just can’t use await, then I’d suggest using then. So, instead of using redisClient.get(key, callback) you could use

    redisClient.get(key).then(successCallback).catch(failureCallback)
    

    That being said, I strongly recommend looking at cacheman-redis and also becoming familiar with async/await functions and promises. Each will simplify your code greatly.

    Login or Signup to reply.
  2. redisClient.connect(); does not really wait before connection succeeds. If you are running the commands before it has a successful connection it wouldn’t work. You need to wait before it’s connected and then it’s safe to run Redis commands.

    You can remove redisClient.connect(); from your redis.js file and use it in index.js where you connect it.

    const redisClient = require('../db/redis');
    (async () => {
      await redisClient.connect();
      // Redis is connected and do your stuff below
    
    })();
    

    example-source

    Also, I’d recommend you to connect Redis at first and when successful then start the server.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search