Home > Mobile >  How to use redis as a module within a nodejs aplication?
How to use redis as a module within a nodejs aplication?

Time:01-22

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.

CodePudding user response:

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.

CodePudding user response:

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.

  •  Tags:  
  • Related