fix: replace N+1 API calls in MyTreesPage with 2 parallel requests

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 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-10 17:53:42 -05:00
parent e5e5922097
commit 0c9fbdc90b

View File

@@ -38,33 +38,26 @@ export function MyTreesPage() {
if (!user?.id) return if (!user?.id) return
setIsLoading(true) setIsLoading(true)
try { try {
// Get user's trees (authored by current user) // Fetch trees and recent sessions in parallel (2 API calls total, not N+1)
const userTrees = await treesApi.list({ author_id: user.id }) const [userTrees, recentSessions] = await Promise.all([
treesApi.list({ author_id: user.id }),
sessionsApi.list({ size: 100 }),
])
// Load session stats for each tree // Build a map of tree_id -> most recent session start time
const treesWithStats = await Promise.all( const lastUsedMap = new Map<string, string>()
userTrees.map(async (tree) => { for (const session of recentSessions) {
try { const existing = lastUsedMap.get(session.tree_id)
const sessions = await sessionsApi.list({ tree_id: tree.id }) if (!existing || new Date(session.started_at) > new Date(existing)) {
const lastUsed = sessions.length > 0 lastUsedMap.set(session.tree_id, session.started_at)
? sessions.reduce((latest, session) => }
new Date(session.started_at) > new Date(latest.started_at) ? session : latest }
).started_at
: undefined const treesWithStats: TreeWithStats[] = userTrees.map((tree) => ({
return { ...tree,
...tree, lastUsed: lastUsedMap.get(tree.id),
lastUsed, sessionCount: tree.usage_count ?? 0,
sessionCount: sessions.length, }))
}
} catch (err) {
console.error(`Failed to load stats for tree ${tree.id}:`, err)
return {
...tree,
sessionCount: 0,
}
}
})
)
setTrees(treesWithStats) setTrees(treesWithStats)
} catch (err) { } catch (err) {