Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis won't retrieve data from cache

I'm following a tutorial and I created a cache.js file that takes the mongoose query and JSON.stringifies it into the key for the values being returned by that query. The goal is to cache that and then append .cache() inside app.js where the mongoose.find() is

Currenty if the cache is empty, I have it do a GET from the DB and then store it in the cache. I have a

console.log("CACHE VALUE #2");
console.log(cacheValue1);

that ensures that the data is getting stored and outputs the data successfully. This line works. But with this line,

console.log("CACHE VALUE #1");
console.log(cacheValue);

the cacheValue is null.

Why is that?

It stores at the bottom the value and the key never changes so I don't understand why it won't return the data instead of null.

So Cache Value #1 is always null and Cache Value #2 has the correct data.

CONSOLE OUTPUT:

GRABBING FROM DB
CLIENT CONNECTION STATUS: true
Setting CACHE to True
ABOUT TO RUN A QUERY
{"$and":[{"auctionType":{"$eq":"publicAuction"}},{"auctionEndDateTime":{"$gte":1582903244869}},{"blacklistGroup":{"$ne":"5e52cca7180a7605ac94648f"}},{"startTime":{"$lte":1582903244869}}],"collection":"listings"}
CACHE VALUE #1
null
CACHE VALUE #2
(THIS IS WHERE ALL MY DATA SHOWS UP)
const mongoose = require('mongoose');
const redis = require('redis');
const util = require('util');
var env = require("dotenv").config({ path: './.env' });

const client = redis.createClient(6380, process.env.REDISCACHEHOSTNAME + '.redis.cache.windows.net', {
  auth_pass: process.env.REDISCACHEKEY,
  tls: { servername: process.env.REDISCACHEHOSTNAME + '.redis.cache.windows.net' }
});


client.get = util.promisify(client.get);


const exec = mongoose.Query.prototype.exec;

mongoose.Query.prototype.cache = function () {
  this.useCache = true;
  console.log("Setting CACHE to True")
  return this;
}

mongoose.Query
  .prototype.exec = async function () {
    if (!this.useCache) {
      console.log("GRABBING FROM DB")
      console.log("CLIENT CONNECTION STATUS: " + client.connected);

      return exec.apply(this, arguments);
    }

    console.log("ABOUT TO RUN A QUERY")
    const key = JSON.stringify(Object.assign({}, this.getQuery(), {
      collection: this.mongooseCollection.name
    }));


    //See if we have a value for 'key' in redis
    console.log(key);
    const cacheValue = await client.get(key);
    console.log("CACHE VALUE #1");
    console.log(cacheValue);
    //If we do, return that
    if (cacheValue) {
      console.log("cacheValue IS TRUE");
      const doc = JSON.parse(cacheValue);
      return Array.isArray(doc)
        ? doc.map(d => new this.model(d))
        : new this.model(doc);
    }

    //Otherwise, issue the query and store the result in redis
    const result = await exec.apply(this, arguments);

    let redisData = JSON.stringify(result);
    //stores the mongoose query result in redis



    await client.set(key, JSON.stringify(redisData)), function (err) {
      console.error(err);

    }
    const cacheValue1 = await client.get(key);
    console.log("CACHE VALUE #2");
    console.log(cacheValue1);




    return result;
  }


like image 402
user6680 Avatar asked Feb 24 '20 17:02

user6680


People also ask

How fetch data from Redis?

During fetching the records from database,first check whether the key present(primary key i.e id) in redis,if "yes" get data directly from redis,otherwise hit the database for data. Suppose database tables are posts,comments.

Is Redis read through cache?

Redis Enterprise provides the best-in-class caching solution This is the most common way to use Redis as a cache. With this strategy, the application first looks into the cache to retrieve the data. If data is not found (cache miss), the application then retrieves the data from the operational data store directly.

How do I know if Redis cache is empty?

The way to test for this in Redis is to simply query the key. If the key is empty, populate it. If it is a string use get (or exists). If it is a hash then query for the specific members you need.


1 Answers

Based on the pastebin you linked, your queries are using Date.now() for their values. This means that each time a query is run, you have different values for the timestamp.

Because your keys are the actual query, and the query has dynamic values based on Date.now(), your keys will never be the same, which is why you can't find them in the cache later, each query is generating a unique key because of the dynamic values of Date.now().

like image 59
Jon Church Avatar answered Nov 15 '22 09:11

Jon Church