perf: eliminate findUnique roundtrip with optimistic direct insert & eager prisma connect

This commit is contained in:
Tien Tran committed 2026-09-28 23:28:12 -07:00
1 parent bb135dbc9e
commit fec54aab1f
2 files changed
+72 -49

No files matched your search

+69 -49
View File
@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
import { prisma } from "@/lib/prisma"; import { prisma } from "@/lib/prisma";
import { getCurrentUser } from "@/lib/auth"; import { getCurrentUser } from "@/lib/auth";
import { generateUniqueShortCode } from "@/lib/short-code"; import { generateRandomCode, getDefaultUrlLength } from "@/lib/short-code";
import { generateQRCodeDataUrl } from "@/lib/qr"; import { generateQRCodeDataUrl } from "@/lib/qr";
export async function POST(req: Request) { export async function POST(req: Request) {
@@ -41,37 +41,6 @@ export async function POST(req: Request) {
); );
} }
// Determine short code
let shortCode = "";
if (custom_code && typeof custom_code === "string") {
const trimmedCode = custom_code.trim();
if (!/^[a-zA-Z0-9_-]{3,20}$/.test(trimmedCode)) {
return NextResponse.json(
{ success: false, message: "Mã rút gọn chỉ chứa chữ cái, chữ số, dấu gạch dưới hoặc gạch ngang (từ 3-20 ký tự)" },
{ status: 422 }
);
}
// Check collision
const existing = await prisma.shortUrl.findUnique({
where: { shortCode: trimmedCode },
});
if (existing) {
return NextResponse.json({ success: false, message: "Mã rút gọn này đã được sử dụng. Vui lòng chọn mã khác." }, { status: 409 });
}
shortCode = trimmedCode;
} else {
// Auto-generate using configured default_url_length
shortCode = await generateUniqueShortCode();
}
const tCodeGen = performance.now();
// Hash password if set
let hashedPassword: string | null = null;
if (password && typeof password === "string" && password.trim().length >= 4) {
hashedPassword = await bcrypt.hash(password.trim(), 10);
}
// Process Tags // Process Tags
let tagConnectList: { name: string }[] = []; let tagConnectList: { name: string }[] = [];
if (tags && typeof tags === "string") { if (tags && typeof tags === "string") {
@@ -93,32 +62,84 @@ export async function POST(req: Request) {
} }
} }
// Create ShortUrl in DB immediately (instant response) // Hash password if set
const createdUrl = await prisma.shortUrl.create({ let hashedPassword: string | null = null;
data: { if (password && typeof password === "string" && password.trim().length >= 4) {
hashedPassword = await bcrypt.hash(password.trim(), 10);
}
let customShortCode = "";
if (custom_code && typeof custom_code === "string") {
const trimmedCode = custom_code.trim();
if (!/^[a-zA-Z0-9_-]{3,20}$/.test(trimmedCode)) {
return NextResponse.json(
{ success: false, message: "Mã rút gọn chỉ chứa chữ cái, chữ số, dấu gạch dưới hoặc gạch ngang (từ 3-20 ký tự)" },
{ status: 422 }
);
}
customShortCode = trimmedCode;
}
// Prepare insert data
const insertData: any = {
originalUrl: url.trim(), originalUrl: url.trim(),
shortCode,
title: null, title: null,
password: hashedPassword, password: hashedPassword,
expiresAt: expirationDate, expiresAt: expirationDate,
displayOnPortal: Boolean(display_on_portal), displayOnPortal: Boolean(display_on_portal),
userId: user ? user.id : null, userId: user ? user.id : null,
tags: { };
if (tagConnectList.length > 0) {
insertData.tags = {
connectOrCreate: tagConnectList.map((tag) => ({ connectOrCreate: tagConnectList.map((tag) => ({
where: { name: tag.name }, where: { name: tag.name },
create: { name: tag.name }, create: { name: tag.name },
})), })),
}, };
}, }
include: {
tags: true, let finalShortCode = customShortCode;
}, let createdUrl: any = null;
if (customShortCode) {
const existing = await prisma.shortUrl.findUnique({
where: { shortCode: customShortCode },
select: { id: true },
}); });
const tDbCreate = performance.now(); if (existing) {
return NextResponse.json({ success: false, message: "Mã rút gọn này đã được sử dụng. Vui lòng chọn mã khác." }, { status: 409 });
}
createdUrl = await prisma.shortUrl.create({
data: { ...insertData, shortCode: customShortCode },
include: tagConnectList.length > 0 ? { tags: true } : undefined,
});
} else {
// Optimistic single-roundtrip direct insert (No pre-checking query needed)
const length = await getDefaultUrlLength();
for (let attempt = 0; attempt < 3; attempt++) {
const candidateCode = generateRandomCode(length + (attempt > 0 ? 1 : 0));
try {
createdUrl = await prisma.shortUrl.create({
data: { ...insertData, shortCode: candidateCode },
include: tagConnectList.length > 0 ? { tags: true } : undefined,
});
finalShortCode = candidateCode;
break;
} catch (err: any) {
if (err.code === "P2002" && attempt < 2) {
continue; // Collision retry
}
throw err;
}
}
}
const tDb = performance.now();
// Build absolute short URL // Build absolute short URL
const appUrl = (process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000").replace(/\/$/, ""); const appUrl = (process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000").replace(/\/$/, "");
const fullShortUrl = `${appUrl}/${shortCode}`; const fullShortUrl = `${appUrl}/${finalShortCode}`;
// Generate QR Code // Generate QR Code
const qrCodeDataUrl = await generateQRCodeDataUrl(fullShortUrl, { size: 240 }); const qrCodeDataUrl = await generateQRCodeDataUrl(fullShortUrl, { size: 240 });
@@ -128,7 +149,7 @@ export async function POST(req: Request) {
success: true, success: true,
data: { data: {
id: createdUrl.id, id: createdUrl.id,
short_code: shortCode, short_code: finalShortCode,
short_url: fullShortUrl, short_url: fullShortUrl,
original_url: createdUrl.originalUrl, original_url: createdUrl.originalUrl,
title: createdUrl.title, title: createdUrl.title,
@@ -136,13 +157,12 @@ export async function POST(req: Request) {
expires_at: createdUrl.expiresAt, expires_at: createdUrl.expiresAt,
is_password_protected: Boolean(createdUrl.password), is_password_protected: Boolean(createdUrl.password),
display_on_portal: createdUrl.displayOnPortal, display_on_portal: createdUrl.displayOnPortal,
tags: createdUrl.tags.map((t) => t.name), tags: createdUrl.tags ? createdUrl.tags.map((t: any) => t.name) : [],
}, },
_timings: { _timings: {
auth_ms: Math.round(tAuth - t0), auth_ms: Math.round(tAuth - t0),
code_gen_ms: Math.round(tCodeGen - tAuth), db_insert_ms: Math.round(tDb - tAuth),
db_create_ms: Math.round(tDbCreate - tCodeGen), qr_ms: Math.round(tQr - tDb),
qr_ms: Math.round(tQr - tDbCreate),
total_server_ms: Math.round(tQr - t0), total_server_ms: Math.round(tQr - t0),
}, },
}); });
+3
View File
@@ -11,3 +11,6 @@ export const prisma =
}); });
globalForPrisma.prisma = prisma; globalForPrisma.prisma = prisma;
// Eagerly initiate database connection in background to avoid cold handshake latency
prisma.$connect().catch(() => {});