Search code examples
node.jscachingtwittertwitter-api-v2

Caching in NODEJS


I am trying to cache the results of the Twitter query as they have rate limiting and I cannot seem to figure it out. I am following this tutorial here.

The Cache.js file looks like so (taken from tutorial):

import NodeCache from 'node-cache';

class Cache {

constructor(ttlSeconds) {
this.cache = new NodeCache({ stdTTL: ttlSeconds, checkperiod: ttlSeconds * 0.2, useClones: false });
}

get(key, storeFunction) {
const value = this.cache.get(key);
if (value) {
  return Promise.resolve(value);
}

return storeFunction().then((result) => {
  this.cache.set(key, result);
  return result;
});
}

del(keys) {
this.cache.del(keys);
}

delStartWith(startStr = '') {
if (!startStr) {
  return;
}

const keys = this.cache.keys();
for (const key of keys) {
  if (key.indexOf(startStr) === 0) {
    this.del(key);
  }
}
}

flush() {
this.cache.flushAll();
}
}

export default Cache;

My Twitter query file looks like so :

import TwitterCount from "../models/TwitterModel.js";
import { TwitterApi } from 'twitter-api-v2';
import dotenv from "dotenv";
dotenv.config();

import CacheService from '../middleware/Cache.js';

const twitterClient = new TwitterApi(process.env.TWITTER_API_BEARER_TOKEN);
const readOnlyClient = twitterClient.readOnly;

const ttl = 60 * 60 * 1; //cache for 1 hour
const cache = new CacheService(ttl);

export const getCount = async(req, res) => {

try {

    const twit = await TwitterCount.findOne({
        attributes:['followersCount']
    });

    const key = `Twit_${String(twit.dataValues.followersCount)}`;

    const twitterFollowers = await readOnlyClient.v2.followers('1563787278857785350'); //HejOfficial account Twitter
    const results = cache.get( key , () => twitterFollowers.data.length );

    if (twit.dataValues.followersCount === results) {

        console.log('same results');

    } else {
        
        await TwitterCount.create({
            followersCount: results
        });
    
        console.log("Twitter Data added Successful");

    }

    res.json(twit);
    cache.del(key);

} catch (error) {
    console.log(error);
}

}

I presume that I am not using the key properly. Please assist if you have encountered this issue before, or provide a better caching alternative.

Thank you.


Solution

  • Try to use the account id as the key, rather than follower count. This way you are caching the accounts followers for an hour.

    Something like this should get you going with the cache, it doesn't have the database inserts, but they can be handled now in the getCount method.

    export const getCount = async(req, res) => {
      const result = await getCountFromAPI("1563787278857785350") //HejOfficial account Twitter
      res.json(result);
    };
    
    const getCountFromAPI = async(account) => {
      const key = `Twit_${account}`;
    
      return cache.get(key, async() => {
        const twitterFollowers = await readOnlyClient.v2.followers(account);
        return twitterFollowers;
      });
    };

    Note that if you save the results to your database every time, it defeats the purpose of the cache. I'd suggest only using the API for this data, and if you want to use database as well, maybe the cache is unnessesary? Save the follower count and account id with time-updated value, and if time updated is more than one hour ago, then query the value again from Twitter.