Skip to content

udemonia/node-redis-caching

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Node Cachine Server

Redis is an in memory data store. Redis allows you to read and write data very quickly.

Once it gets turned off, restarted, or after an alloted amount of time, the data is gone.

Node Redis

We're going to be using the redis package on npm to interface with our local redis server.

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

Setting up Redis

Make sure that the service is running on the server/host machine

For this project, I installed redis with home brew

brew services start redis

you can then open the redis cli

redis-cli

in our node applicaiton, we want to npm install redis

npm i redis

We will create a custom middleware for checking cache - if the resource doesn't exist, we will call next and pass it to axios for the api call.

// bring redis in
const redis = require("redis");

// create the redis client
const client = redis.createClient(REDIS_PORT);

//* CACHE MIDDLEWARE
function cache(req, res, next) {
  //* pull out the username from the request param
  const { username } = req.params;

  //? Attempt to pull out the cache data from Redis
  client.get(username, (err, data) => {
    // node js, error first design pattern
    if (err) throw err;
    //* if there is data, respond with it - holding it for 3600 seconds
    if (data) {
      res.send(setResponse(username, data));
    } else {
      //* if there is no data - we will call next, which would be a non cached call
      next();
    }
  });
}

//? Make req to github for data
const getRepos = async (req, res, next) => {
  try {
    let { username } = req.params;
    const response = await axios.get(
      `https://api.github.com/users/${username}`
    );
    const repos = response.data.public_repos;

    //* set data w/ redis - setEx = set with expiration
    //* key, time, data to cache
    client.setex(username, 3600, repos);

    res.send(setResponse(username, repos));
  } catch (error) {
    console.log("error");
    res.status(500);
  }
};

app.get("/repos/:username", cache, getRepos);

app.listen(PORT, () => {
  console.log(chalk.red.bold(`Listening on port: ${PORT}`));
});

Setex

With redis, on write, we can call setex - which sets the data within the redis store with an expiration

Redis setex takes three arguments

  • the key

  • the time to hold on the data in seconds

  • the data to associate with the key

Redis client.get

We can call client.get and pass the username and a callback

If there is data, we will respond with it - otherwise, we will pass the request over to route for the axios networking i/o call.

Ping Pong w/ Redis

 udemonia@root: ~/dev/javaScript/node/redis-node [git:master]
🤓 $redis-cli ping
PONG

How does Redis work?

Similar to a JavaScript object - its a key/value in memory store

set

set or setex

Get

get - is an async operation, we need to pass a callback function.

Redis REPL

 udemonia@root: ~/dev/javaScript/node/redis-node [git:master]
🪐 $node
Welcome to Node.js v16.11.1.
Type ".help" for more information.
> const redis = require('redis')
undefined
> const redisURL = 'redis://127.0.0.1:6379'
undefined
> const client = redis.createClient(redisURL)
undefined
> client.set('Hi', 'There')
true
> client.get('Hi', (err, data) => {
... if (err) throw err;
... console.log(data)
... }
... )
true
> There
> client.get('Hi', console.log)
true
> null There

Nested Key/Value Pairs

We can also nest key/value pairs, where the value for a key is itself a key for another value.

alt text

To handle this, we need to use a different set method

hset('spanish', 'red', 'rojo')

  • the master key (overall key)

  • red is modifying that value

  • the value inside of the nested hash

To retrieve values

hget('spanish', 'red', (err, data) => console.log(data)

> client.hset('German', 'red', 'rot')
true
> client.hget('German', 'red', (err,data) => console.log(data))
true
> rot
> client.hset('German', 'blue', 'blau')
true
> client.hget('German', 'blue', console.log)
true
> null blau

Redis Gotcha

We can only store numbers and letters - we can't store a plain JavaScript object within redis...

Redis will convert a JS object into [object Object] or error out...

To get around this, we have to stringify objects....

> client.set('JS-Object', {this: 'is an object'})
Uncaught Error: node_redis: The SET command contains a invalid argument type.
Only strings, dates and buffers are accepted. Please update your code to use valid argument types.
    at RedisClient.internal_send_command (/Users/brandonlambert/dev/javaScript/node/redis-node/node_modules/redis/index.js:835:39)
    at RedisClient.set (/Users/brandonlambert/dev/javaScript/node/redis-node/node_modules/redis/lib/commands.js:46:25) {
  command: 'SET',
  args: [ 'JS-Object', { this: 'is an object' } ]
}
> client.set('JS-Object', JSON.stringify({red: 'rojo'}))
true
> client.get('JS-Object')
true
> client.get('JS-Object', (err,data) => console.log(data))
true
> {"red":"rojo"}

We can also call JSON.parse on the string coming back - to turn it into an object again :)

> client.get('JS-Object', (err,data) => console.log(JSON.parse(data)))
true
> { red: 'rojo' }

About

example code for Node Redis Caching

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published