diff --git a/.jules/bolt.md b/.jules/bolt.md index 43fafef..6530d65 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -5,3 +5,7 @@ ## 2024-05-18 - Concurrent Fetching with Owner IDs in Share Links **Learning:** In the share system, endpoints processing a share code typically suffer from waterfall latency by first loading target entity details (like a project) and then querying its associated elements (like project lists) using the entity's owner ID (`userId`). However, the `shareLink` object already contains the `userId` field (representing the owner's ID). **Action:** Always leverage the existing owner's ID within `shareLink` to bypass sequential dependencies and fetch parent entities (like projects) concurrently with their child elements (like user lists) using `Promise.all`. + +## 2024-05-23 - Concurrent Parent/Child Data Fetching in API Routes +**Learning:** In backend API routes (e.g. GET requests for entities), sequentially awaiting a parent validation query (like `getProject(userId, projectId)`) and then its child data query (`getProjectLists(userId, projectId)`) creates a database query waterfall that adds unnecessary latency. +**Action:** When the child query does not strictly depend on the result of the parent query (for example, when both rely on existing parameters like `userId` and `projectId`/`listId`), execute both queries concurrently using `Promise.all` and then perform the necessary validation checks (e.g. `if (!project) return 404`). diff --git a/src/app/api/lists/[id]/citations/[citationId]/route.ts b/src/app/api/lists/[id]/citations/[citationId]/route.ts index df341ec..214d2a5 100644 --- a/src/app/api/lists/[id]/citations/[citationId]/route.ts +++ b/src/app/api/lists/[id]/citations/[citationId]/route.ts @@ -21,7 +21,12 @@ export async function GET(request: NextRequest, { params }: RouteParams) { } // Verify the list exists and belongs to the user - const list = await getList(userId, listId); + // Fetch list details and citation concurrently by utilizing the userId + const [list, citation] = await Promise.all([ + getList(userId, listId), + getCitation(listId, citationId), + ]); + if (!list) { return NextResponse.json( { success: false, error: "List not found" }, @@ -29,8 +34,6 @@ export async function GET(request: NextRequest, { params }: RouteParams) { ); } - const citation = await getCitation(listId, citationId); - if (!citation) { return NextResponse.json( { success: false, error: "Citation not found" }, diff --git a/src/app/api/lists/[id]/citations/route.ts b/src/app/api/lists/[id]/citations/route.ts index a02efd7..a1220fe 100644 --- a/src/app/api/lists/[id]/citations/route.ts +++ b/src/app/api/lists/[id]/citations/route.ts @@ -22,7 +22,12 @@ export async function GET(request: NextRequest, { params }: RouteParams) { } // Verify the list exists and belongs to the user - const list = await getList(userId, listId); + // Fetch list details and list citations concurrently by utilizing the userId + const [list, citations] = await Promise.all([ + getList(userId, listId), + getListCitations(listId), + ]); + if (!list) { return NextResponse.json( { success: false, error: "List not found" }, @@ -30,8 +35,6 @@ export async function GET(request: NextRequest, { params }: RouteParams) { ); } - const citations = await getListCitations(listId); - return NextResponse.json({ success: true, data: citations, diff --git a/src/app/api/projects/[id]/lists/route.ts b/src/app/api/projects/[id]/lists/route.ts index 85b2e9f..ce8110e 100644 --- a/src/app/api/projects/[id]/lists/route.ts +++ b/src/app/api/projects/[id]/lists/route.ts @@ -21,7 +21,12 @@ export async function GET(request: NextRequest, { params }: RouteParams) { } // Verify the project exists and belongs to the user - const project = await getProject(userId, projectId); + // Fetch project details and user lists concurrently by utilizing the userId + const [project, lists] = await Promise.all([ + getProject(userId, projectId), + getProjectLists(userId, projectId), + ]); + if (!project) { return NextResponse.json( { success: false, error: "Project not found" }, @@ -29,8 +34,6 @@ export async function GET(request: NextRequest, { params }: RouteParams) { ); } - const lists = await getProjectLists(userId, projectId); - return NextResponse.json({ success: true, data: lists,