chore: performance improvements moving ratelimit to redis

This commit is contained in:
2024-12-24 17:42:00 +01:00
parent 545e7668e7
commit 46363fead1
3 changed files with 45 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
import prisma from '@/lib/db';
import redis from '@/lib/db/redis';
import ratelimit from '@/lib/ratelimit';
export const dynamic = 'force-dynamic';
@@ -6,22 +7,19 @@ export const dynamic = 'force-dynamic';
export async function POST(request: Request, { params }: { params: Promise<{ projectId: string }> }) {
const { projectId } = await params;
const body = await request.json();
const queryProject = await prisma.project.findFirst({
where: {
id: projectId,
},
});
if (!queryProject) {
const ratelimitInfo = await redis.get(`ratelimit:${projectId}`);
if (!ratelimitInfo) {
return Response.json({ success: false, error: 'Project not found' }, { status: 404 });
}
// TODO: optimize to query redis instead of prisma first.
const [rateLimitReq, rateLimitTime] = ratelimitInfo.split(':').map(Number);
const ip = request.headers.get('x-forwarded-for') || request.headers.get('cf-connecting-ip');
const queryRL = await ratelimit(
ip!,
queryProject.id,
queryProject.rateLimitReq,
queryProject.rateLimitTime
projectId,
rateLimitReq,
rateLimitTime
);
if (queryRL.exceeded) {
return Response.json(
@@ -33,6 +31,15 @@ export async function POST(request: Request, { params }: { params: Promise<{ pro
);
}
const queryProject = await prisma.project.findFirst({
where: {
id: projectId,
},
});
if (!queryProject) {
return Response.json({ success: false, error: 'Project not found' }, { status: 404 });
}
// Convert customKeys to regular array and add message
const customKeys = [...queryProject.customData, 'message'];
const bodyKeys = Object.keys(body);

23
src/instrumentation.ts Normal file
View File

@@ -0,0 +1,23 @@
import prisma from './lib/db';
export async function register() {
try {
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { default: Redis } = await import('ioredis');
const redis = new Redis(process.env.REDIS_URL!);
console.log('Uploading all ratelimits to redis...');
const ratelimits = (await prisma.project.findMany()).map((pr) => {
return { req: pr.rateLimitReq, time: pr.rateLimitTime, project: pr.id };
});
const multi = redis.multi();
multi.del('ratelimit:*');
ratelimits.forEach((rl) => {
multi.set(`ratelimit:${rl.project}`, `${rl.req}:${rl.time}`);
});
await multi.exec();
console.log('All ratelimits uploaded to redis!');
}
} catch {}
}

View File

@@ -13,6 +13,7 @@ import prisma from '../db';
import zodVerify from '../zodVerify';
import { createSchema } from './zod';
import { octokitApp } from '../octokitApp';
import redis from '../db/redis';
export async function create(prev: any, formData: FormData) {
const zod = await zodVerify(createSchema, formData);
@@ -35,6 +36,8 @@ export async function create(prev: any, formData: FormData) {
},
},
});
redis.set(`ratelimit:${dbCreate.id}`, `${dbCreate.rateLimitReq}:${dbCreate.rateLimitTime}`);
return { success: true, id: dbCreate.id };
}
@@ -79,6 +82,8 @@ export async function ratelimitChange(prev: any, formData: FormData) {
rateLimitTime: zod.data.duration,
},
});
redis.set(`ratelimit:${zod.data.id}`, `${zod.data.requests}:${zod.data.duration}`);
return { success: true, id: dbUpdate.id };
}