Skip to content

Commit

Permalink
implemented caching using redis (#99) close issue#49
Browse files Browse the repository at this point in the history
* added caching

* implemented caching

* implemented chaching

* .

* .

* added dependencies

* updated SAMPLE.env.local

* .

* updated README.md and restored app/api/Tickets/[id]/route.js
  • Loading branch information
disvid authored Jan 14, 2025
1 parent f4fa176 commit f595760
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 16 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ npm install

Replace `<no-of-tickets-to-be-shown-per-page-by-default>` with the number of tickets you want to show by default per page.

```env
# Redis Configuration
REDIS_HOST=127.0.0.1 # Replace with your Redis server's IP or hostname
REDIS_PORT=6379 # Default Redis port
```
- Install and configure Redis on your local machine or use a cloud-hosted Redis instance.
- Replace `<REDIS_HOST>` and `<REDIS_PORT>` with the appropriate values for your Redis server.

### 5. Start the Development Server
```bash
npm run dev
Expand Down
4 changes: 3 additions & 1 deletion SAMPLE.env.local
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
MONGODB_URI=mongodb+srv://yourUSER:[email protected]/MondayClone
MONGODB_URI=mongodb+srv://yourUSER:[email protected]/MondayClone
REDIS_HOST=127.0.0.1 # Replace with your Redis server's IP or hostname
REDIS_PORT=6379 # Default Redis port
48 changes: 33 additions & 15 deletions app/api/Tickets/route.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
import Ticket from "@/app/models/Ticket";
import { createClient } from 'redis';
import { NextResponse } from "next/server";

export async function GET(req) {
const cacheKey = "tickets";
const redisClient = createClient();
redisClient.on('error', err => console.log('Redis Client Error', err));

await redisClient.connect();

try {
// Get the URL from the request object
const url = new URL(req.url);

// Extract query parameters using URLSearchParams
const page = url.searchParams.get('page') || 1; // Default page is 1
const ticketsNo = url.searchParams.get('ticketsNo') || process.env.TICKETS_NO || 10; // Default tickets per page is 10 or as defined in env file
const page = parseInt(url.searchParams.get('page')) || 1;
const ticketsNo = parseInt(url.searchParams.get('ticketsNo')) || parseInt(process.env.TICKETS_NO) || 10;

// Get the total number of tickets (for calculating totalPages)
const totalTickets = await Ticket.countDocuments();
const totalPages = Math.ceil(totalTickets / ticketsNo);
const cacheKeyWithParams = `${cacheKey}-${page}-${ticketsNo}`;
const cachedData = await redisClient.get(cacheKeyWithParams);

if (!url.searchParams.get('page') && !url.searchParams.get('ticketsNo')) {
const tickets = await Ticket.find()
return NextResponse.json({ tickets }, { status: 200 });
if (cachedData) {
console.log("Cache hit for tickets");
return NextResponse.json(JSON.parse(cachedData));
}

console.log("Cache miss for tickets");

const totalTickets = await Ticket.countDocuments();
const totalPages = Math.ceil(totalTickets / ticketsNo);

const tickets = await Ticket.find().skip((page - 1) * ticketsNo).limit(ticketsNo);
return NextResponse.json({ hasNext: (page < totalPages), totalPages, totalTickets, tickets }, { status: 200 });

const responseData = {
hasNext: page < totalPages,
totalPages,
totalTickets,
tickets,
};

await redisClient.set(cacheKeyWithParams, JSON.stringify(responseData), { EX: 3600 });

return NextResponse.json(responseData, { status: 200 });
} catch (err) {
console.log(err);
return NextResponse.json({ message: "Error", err }, { status: 500 });
} finally {
redisClient.disconnect();
}
}

Expand All @@ -32,7 +53,6 @@ export async function POST(req) {
const body = await req.json();
const ticketData = body.formData;


if (ticketData.status === "not started") {
await Ticket.create(ticketData);
return NextResponse.json({ message: "Ticket Created" }, { status: 201 });
Expand All @@ -46,6 +66,4 @@ export async function POST(req) {
console.log(err);
return NextResponse.json({ message: "Error", err }, { status: 500 });
}
}


}
20 changes: 20 additions & 0 deletions app/redisClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createClient } from "redis";

let redisClient;

const getRedisClient = async () => {
if (!redisClient) {
redisClient = createClient({
url: `redis://${process.env.REDIS_HOST || "127.0.0.1"}:${process.env.REDIS_PORT || 6379}`,
});

redisClient.on("error", (err) => console.error("Redis error:", err));

if (!redisClient.isOpen) {
await redisClient.connect();
}
}
return redisClient;
};

export default getRedisClient;
156 changes: 156 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"postcss": "^8.4.49",
"react": "18.2.0",
"react-dom": "18.2.0",
"redis": "^4.7.0",
"tailwindcss": "3.3.3"
}
}

0 comments on commit f595760

Please sign in to comment.