Skip to content

Commit

Permalink
Merge branch 'thombergs:master' into beginner-guide-to-creating-apach…
Browse files Browse the repository at this point in the history
…e-http-client
  • Loading branch information
sagaofsilence authored Apr 23, 2024
2 parents db1b783 + d5aa933 commit 18f445e
Show file tree
Hide file tree
Showing 6 changed files with 955 additions and 0 deletions.
17 changes: 17 additions & 0 deletions nodejs/nodecache-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Optimizing Node.js Application Performance with Caching

This README provides a quick guide to start a simple Node.js server project.

Install Dependencies

```bash
npm install
```

Start your Node.js server:

```bash
node index.js
```

To check Node Server is Working RUN `http://localhost:7000/api/v1/products`
23 changes: 23 additions & 0 deletions nodejs/nodecache-app/controllers/product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const productController = {
getproducts: async (req, res) => {
// emulating data store delay time to retrieve product data
await new Promise(resolve => setTimeout(resolve, 750));

const products = [
{ id: 1, name: "Desk Bed", price: 854.44 },
{ id: 2, name: "Shelf Table", price: 357.08 },
{ id: 3, name: "Couch Lamp", price: 594.53 },
{ id: 4, name: "Bed Couch", price: 309.62 },
{ id: 5, name: "Desk Shelf", price: 116.39 },
{ id: 6, name: "Couch Lamp", price: 405.03 },
{ id: 7, name: "Rug Chair", price: 47.77 },
{ id: 8, name: "Sofa Shelf", price: 359.85 },
{ id: 9, name: "Desk Table", price: 823.21 },
{ id: 10, name: "Table Shelf", price: 758.91 },
];

res.json({ products });
},
};

module.exports = { productController };
33 changes: 33 additions & 0 deletions nodejs/nodecache-app/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const express = require("express");
const {
initializeRedisClient,
cacheMiddleware,
invalidateCacheMiddleware,
} = require("./middlewares/redis");
const { productController } = require("./controllers/product");

const app = express();
app.use(express.json());

// connect to Redis
initializeRedisClient();

// register an endpoint
app.get(
"/api/v1/products",
cacheMiddleware({
EX: 3600, // 1h
}),
productController.getproducts
);

app.post("/api/v1/product", invalidateCacheMiddleware, (req, res) => {
// Implement your logic to update data in Application data store
res.json({ message: "Product data updated successfully" });
});

// start the server
const port = 7000;
app.listen(port, () => {
console.log(`Server is running on port: http://localhost:${port}`);
});
74 changes: 74 additions & 0 deletions nodejs/nodecache-app/middlewares/redis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const { createClient } = require("redis");
const hash = require("object-hash");
let redisClient;

async function initializeRedisClient() {
try {
redisClient = createClient();
await redisClient.connect();
console.log("Redis Connected Successfully");
} catch (e) {
console.error(`Redis connection failed with error:`);
console.error(e);
}
}

function generateCacheKey(req, method = "GET") {
let type = method.toUpperCase();
// build a custom object to use as a part of our Redis key
const reqDataToHash = {
query: req.query,
};
return `${type}-${req.path}/${hash.sha1(reqDataToHash)}`;
}

function cacheMiddleware(
options = {
EX: 10800, // 3h
}
) {
return async (req, res, next) => {
if (redisClient?.isOpen) {
const key = generateCacheKey(req, req.method);

//if cached data is found retrieve it
const cachedValue = await redisClient.get(key);

if (cachedValue) {
return res.json(JSON.parse(cachedValue));
} else {
const oldSend = res.send;

// When the middleware function redisCachingMiddleware is executed, it replaces the res.send function with a custom function.
res.send = async function saveCache(data) {
res.send = oldSend;

// cache the response only if it is successful
if (res.statusCode >= 200 && res.statusCode < 300) {
await redisClient.set(key, data, options);
}

return res.send(data);
};

// continue to the controller function
next();
}
} else {
next();
}
};
}

function invalidateCacheMiddleware(req, res, next) {
// Invalidate the cache for the cache key
const key = generateCacheKey(req);
redisClient.del(key);
next();
}

module.exports = {
initializeRedisClient,
cacheMiddleware,
invalidateCacheMiddleware,
};
Loading

0 comments on commit 18f445e

Please sign in to comment.