Skip to content

Commit d5aa933

Browse files
authored
nodejs cache app (#301)
1 parent 0a30e90 commit d5aa933

File tree

6 files changed

+955
-0
lines changed

6 files changed

+955
-0
lines changed

nodejs/nodecache-app/README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Optimizing Node.js Application Performance with Caching
2+
3+
This README provides a quick guide to start a simple Node.js server project.
4+
5+
Install Dependencies
6+
7+
```bash
8+
npm install
9+
```
10+
11+
Start your Node.js server:
12+
13+
```bash
14+
node index.js
15+
```
16+
17+
To check Node Server is Working RUN `http://localhost:7000/api/v1/products`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const productController = {
2+
getproducts: async (req, res) => {
3+
// emulating data store delay time to retrieve product data
4+
await new Promise(resolve => setTimeout(resolve, 750));
5+
6+
const products = [
7+
{ id: 1, name: "Desk Bed", price: 854.44 },
8+
{ id: 2, name: "Shelf Table", price: 357.08 },
9+
{ id: 3, name: "Couch Lamp", price: 594.53 },
10+
{ id: 4, name: "Bed Couch", price: 309.62 },
11+
{ id: 5, name: "Desk Shelf", price: 116.39 },
12+
{ id: 6, name: "Couch Lamp", price: 405.03 },
13+
{ id: 7, name: "Rug Chair", price: 47.77 },
14+
{ id: 8, name: "Sofa Shelf", price: 359.85 },
15+
{ id: 9, name: "Desk Table", price: 823.21 },
16+
{ id: 10, name: "Table Shelf", price: 758.91 },
17+
];
18+
19+
res.json({ products });
20+
},
21+
};
22+
23+
module.exports = { productController };

nodejs/nodecache-app/index.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const express = require("express");
2+
const {
3+
initializeRedisClient,
4+
cacheMiddleware,
5+
invalidateCacheMiddleware,
6+
} = require("./middlewares/redis");
7+
const { productController } = require("./controllers/product");
8+
9+
const app = express();
10+
app.use(express.json());
11+
12+
// connect to Redis
13+
initializeRedisClient();
14+
15+
// register an endpoint
16+
app.get(
17+
"/api/v1/products",
18+
cacheMiddleware({
19+
EX: 3600, // 1h
20+
}),
21+
productController.getproducts
22+
);
23+
24+
app.post("/api/v1/product", invalidateCacheMiddleware, (req, res) => {
25+
// Implement your logic to update data in Application data store
26+
res.json({ message: "Product data updated successfully" });
27+
});
28+
29+
// start the server
30+
const port = 7000;
31+
app.listen(port, () => {
32+
console.log(`Server is running on port: http://localhost:${port}`);
33+
});
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const { createClient } = require("redis");
2+
const hash = require("object-hash");
3+
let redisClient;
4+
5+
async function initializeRedisClient() {
6+
try {
7+
redisClient = createClient();
8+
await redisClient.connect();
9+
console.log("Redis Connected Successfully");
10+
} catch (e) {
11+
console.error(`Redis connection failed with error:`);
12+
console.error(e);
13+
}
14+
}
15+
16+
function generateCacheKey(req, method = "GET") {
17+
let type = method.toUpperCase();
18+
// build a custom object to use as a part of our Redis key
19+
const reqDataToHash = {
20+
query: req.query,
21+
};
22+
return `${type}-${req.path}/${hash.sha1(reqDataToHash)}`;
23+
}
24+
25+
function cacheMiddleware(
26+
options = {
27+
EX: 10800, // 3h
28+
}
29+
) {
30+
return async (req, res, next) => {
31+
if (redisClient?.isOpen) {
32+
const key = generateCacheKey(req, req.method);
33+
34+
//if cached data is found retrieve it
35+
const cachedValue = await redisClient.get(key);
36+
37+
if (cachedValue) {
38+
return res.json(JSON.parse(cachedValue));
39+
} else {
40+
const oldSend = res.send;
41+
42+
// When the middleware function redisCachingMiddleware is executed, it replaces the res.send function with a custom function.
43+
res.send = async function saveCache(data) {
44+
res.send = oldSend;
45+
46+
// cache the response only if it is successful
47+
if (res.statusCode >= 200 && res.statusCode < 300) {
48+
await redisClient.set(key, data, options);
49+
}
50+
51+
return res.send(data);
52+
};
53+
54+
// continue to the controller function
55+
next();
56+
}
57+
} else {
58+
next();
59+
}
60+
};
61+
}
62+
63+
function invalidateCacheMiddleware(req, res, next) {
64+
// Invalidate the cache for the cache key
65+
const key = generateCacheKey(req);
66+
redisClient.del(key);
67+
next();
68+
}
69+
70+
module.exports = {
71+
initializeRedisClient,
72+
cacheMiddleware,
73+
invalidateCacheMiddleware,
74+
};

0 commit comments

Comments
 (0)