fix(api): optimize /api/tools by removing expensive count query
This commit is contained in:
parent
e14e1340cc
commit
a07b705f80
1 changed files with 76 additions and 91 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
// import { type Prisma, prisma } from '@tpmjs/db';
|
import { type Prisma, prisma } from '@tpmjs/db';
|
||||||
import { NextResponse } from 'next/server';
|
import { type NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
export const runtime = 'nodejs';
|
export const runtime = 'nodejs';
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
@ -16,103 +16,88 @@ export const maxDuration = 60;
|
||||||
* - limit: Results per page (default: 20, max: 100)
|
* - limit: Results per page (default: 20, max: 100)
|
||||||
* - offset: Pagination offset (default: 0)
|
* - offset: Pagination offset (default: 0)
|
||||||
*/
|
*/
|
||||||
export async function GET() {
|
export async function GET(request: NextRequest) {
|
||||||
// Temporary: Return simple response to test if endpoint works
|
try {
|
||||||
return NextResponse.json({
|
const searchParams = request.nextUrl.searchParams;
|
||||||
status: 'ok',
|
|
||||||
message: 'Tools endpoint working (database queries disabled for testing)',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
env: {
|
|
||||||
hasDatabase: !!process.env.DATABASE_URL,
|
|
||||||
databaseUrlPrefix: process.env.DATABASE_URL?.substring(0, 20) + '...', // Show first 20 chars only for security
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// try {
|
// Parse query parameters
|
||||||
// const searchParams = request.nextUrl.searchParams;
|
const query = searchParams.get('q');
|
||||||
|
const category = searchParams.get('category');
|
||||||
|
const officialParam = searchParams.get('official');
|
||||||
|
const limitParam = searchParams.get('limit');
|
||||||
|
const offsetParam = searchParams.get('offset');
|
||||||
|
|
||||||
// // Parse query parameters
|
// Validate and set defaults (reduced max from 100 to 50 for faster queries)
|
||||||
// const query = searchParams.get('q');
|
const limit = Math.min(
|
||||||
// const category = searchParams.get('category');
|
Number.parseInt(limitParam || '20', 10),
|
||||||
// const officialParam = searchParams.get('official');
|
50 // Reduced from 100 for better performance
|
||||||
// const limitParam = searchParams.get('limit');
|
);
|
||||||
// const offsetParam = searchParams.get('offset');
|
const offset = Math.max(Number.parseInt(offsetParam || '0', 10), 0);
|
||||||
|
|
||||||
// // Validate and set defaults
|
// Build where clause
|
||||||
// const limit = Math.min(
|
const where: Prisma.ToolWhereInput = {};
|
||||||
// Number.parseInt(limitParam || '20', 10),
|
|
||||||
// 100 // Max 100 results per page
|
|
||||||
// );
|
|
||||||
// const offset = Math.max(Number.parseInt(offsetParam || '0', 10), 0);
|
|
||||||
|
|
||||||
// // Build where clause
|
// Search filter (case-insensitive partial match)
|
||||||
// const where: Prisma.ToolWhereInput = {};
|
if (query) {
|
||||||
|
where.OR = [
|
||||||
|
{ npmPackageName: { contains: query, mode: 'insensitive' } },
|
||||||
|
{ description: { contains: query, mode: 'insensitive' } },
|
||||||
|
{
|
||||||
|
tags: {
|
||||||
|
hasSome: [query],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// // Search filter (case-insensitive partial match)
|
// Category filter
|
||||||
// if (query) {
|
if (category) {
|
||||||
// where.OR = [
|
where.category = category;
|
||||||
// { npmPackageName: { contains: query, mode: 'insensitive' } },
|
}
|
||||||
// { description: { contains: query, mode: 'insensitive' } },
|
|
||||||
// {
|
|
||||||
// tags: {
|
|
||||||
// hasSome: [query],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Category filter
|
// Official filter
|
||||||
// if (category) {
|
if (officialParam !== null) {
|
||||||
// where.category = category;
|
where.isOfficial = officialParam === 'true';
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Official filter
|
// Execute queries - run count separately only if needed for pagination
|
||||||
// if (officialParam !== null) {
|
// For first page, we can skip count if we don't need total pages
|
||||||
// where.isOfficial = officialParam === 'true';
|
const tools = await prisma.tool.findMany({
|
||||||
// }
|
where,
|
||||||
|
orderBy: [
|
||||||
|
{ qualityScore: 'desc' },
|
||||||
|
{ npmDownloadsLastMonth: 'desc' },
|
||||||
|
{ createdAt: 'desc' },
|
||||||
|
],
|
||||||
|
take: limit + 1, // Fetch one extra to check if there are more
|
||||||
|
skip: offset,
|
||||||
|
});
|
||||||
|
|
||||||
// // Execute query with pagination
|
// Check if there are more results
|
||||||
// const [tools, totalCount] = await Promise.all([
|
const hasMore = tools.length > limit;
|
||||||
// prisma.tool.findMany({
|
const actualTools = hasMore ? tools.slice(0, limit) : tools;
|
||||||
// where,
|
|
||||||
// orderBy: [
|
|
||||||
// { qualityScore: 'desc' },
|
|
||||||
// { npmDownloadsLastMonth: 'desc' },
|
|
||||||
// { createdAt: 'desc' },
|
|
||||||
// ],
|
|
||||||
// take: limit,
|
|
||||||
// skip: offset,
|
|
||||||
// }),
|
|
||||||
// prisma.tool.count({ where }),
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// // Calculate pagination metadata
|
return NextResponse.json({
|
||||||
// const hasMore = offset + limit < totalCount;
|
success: true,
|
||||||
// const totalPages = Math.ceil(totalCount / limit);
|
data: actualTools,
|
||||||
// const currentPage = Math.floor(offset / limit) + 1;
|
pagination: {
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
hasMore,
|
||||||
|
// Note: total count omitted for performance (can be expensive)
|
||||||
|
// Only return count if explicitly requested
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching tools:', error);
|
||||||
|
|
||||||
// return NextResponse.json({
|
return NextResponse.json(
|
||||||
// success: true,
|
{
|
||||||
// data: tools,
|
success: false,
|
||||||
// pagination: {
|
error: 'Failed to fetch tools',
|
||||||
// total: totalCount,
|
message: error instanceof Error ? error.message : 'Unknown error',
|
||||||
// limit,
|
},
|
||||||
// offset,
|
{ status: 500 }
|
||||||
// hasMore,
|
);
|
||||||
// totalPages,
|
}
|
||||||
// currentPage,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('Error fetching tools:', error);
|
|
||||||
|
|
||||||
// return NextResponse.json(
|
|
||||||
// {
|
|
||||||
// success: false,
|
|
||||||
// error: 'Failed to fetch tools',
|
|
||||||
// message: error instanceof Error ? error.message : 'Unknown error',
|
|
||||||
// },
|
|
||||||
// { status: 500 }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue