From 0c9fbdc90b0bb4a53e67cf68da69b922cef5e41d Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Tue, 10 Feb 2026 17:53:42 -0500 Subject: [PATCH] fix: replace N+1 API calls in MyTreesPage with 2 parallel requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page was making 1 API call per tree to fetch session stats, but the backend sessions endpoint doesn't support tree_id filtering — so every call returned identical data. Now fetches trees and sessions in parallel (2 calls total), builds a lastUsed map client-side, and uses the existing usage_count field from the tree list response for session counts. Co-Authored-By: Claude Opus 4.6 --- frontend/src/pages/MyTreesPage.tsx | 45 +++++++++++++----------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/frontend/src/pages/MyTreesPage.tsx b/frontend/src/pages/MyTreesPage.tsx index 144ca376..bb76aed6 100644 --- a/frontend/src/pages/MyTreesPage.tsx +++ b/frontend/src/pages/MyTreesPage.tsx @@ -38,33 +38,26 @@ export function MyTreesPage() { if (!user?.id) return setIsLoading(true) try { - // Get user's trees (authored by current user) - const userTrees = await treesApi.list({ author_id: user.id }) + // Fetch trees and recent sessions in parallel (2 API calls total, not N+1) + const [userTrees, recentSessions] = await Promise.all([ + treesApi.list({ author_id: user.id }), + sessionsApi.list({ size: 100 }), + ]) - // Load session stats for each tree - const treesWithStats = await Promise.all( - userTrees.map(async (tree) => { - try { - const sessions = await sessionsApi.list({ tree_id: tree.id }) - const lastUsed = sessions.length > 0 - ? sessions.reduce((latest, session) => - new Date(session.started_at) > new Date(latest.started_at) ? session : latest - ).started_at - : undefined - return { - ...tree, - lastUsed, - sessionCount: sessions.length, - } - } catch (err) { - console.error(`Failed to load stats for tree ${tree.id}:`, err) - return { - ...tree, - sessionCount: 0, - } - } - }) - ) + // Build a map of tree_id -> most recent session start time + const lastUsedMap = new Map() + for (const session of recentSessions) { + const existing = lastUsedMap.get(session.tree_id) + if (!existing || new Date(session.started_at) > new Date(existing)) { + lastUsedMap.set(session.tree_id, session.started_at) + } + } + + const treesWithStats: TreeWithStats[] = userTrees.map((tree) => ({ + ...tree, + lastUsed: lastUsedMap.get(tree.id), + sessionCount: tree.usage_count ?? 0, + })) setTrees(treesWithStats) } catch (err) {