diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..0552480 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-24 - Optimize Prisma nested include iterations +**Learning:** When calculating totals or metrics from large nested datasets (e.g., from Prisma `include` results), using multiple chained `.reduce()` calls causes multiple iterations over the same data, leading to unnecessary memory allocation and iteration overhead. +**Action:** Replace multiple chained array iteration methods (like `.reduce()`, `.map()`, or `.filter()`) with a single `for...of` loop when aggregating multiple metrics from the same dataset to minimize iteration overhead. diff --git a/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/[sessionId]/route.ts b/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/[sessionId]/route.ts index 35486b8..fa43615 100644 --- a/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/[sessionId]/route.ts +++ b/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/[sessionId]/route.ts @@ -43,9 +43,15 @@ export async function GET( return forbiddenByRole(access.role, '본인 세션만 열람 가능') } - const totalInput = session.usageRecords.reduce((sum, r) => sum + r.inputTokens, 0) - const totalOutput = session.usageRecords.reduce((sum, r) => sum + r.outputTokens, 0) - const totalCost = session.usageRecords.reduce((sum, r) => sum + (r.estimatedCostUsd ?? 0), 0) + let totalInput = 0 + let totalOutput = 0 + let totalCost = 0 + + for (const r of session.usageRecords) { + totalInput += r.inputTokens + totalOutput += r.outputTokens + totalCost += r.estimatedCostUsd ?? 0 + } const usageTimeline: SessionTimelineUsage[] = session.usageRecords.map((r) => ({ timestamp: r.timestamp.toISOString(), diff --git a/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/route.ts b/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/route.ts index 25fbe70..7d6a4d4 100644 --- a/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/route.ts +++ b/packages/web/src/app/api/orgs/[orgSlug]/dashboard/sessions/route.ts @@ -33,14 +33,17 @@ const sessionInclude = { type SessionWithInclude = Prisma.ClaudeSessionGetPayload<{ include: typeof sessionInclude }> function getSessionTotals(session: SessionWithInclude) { - return { - inputTokens: session.usageRecords.reduce((sum, r) => sum + r.inputTokens, 0), - outputTokens: session.usageRecords.reduce((sum, r) => sum + r.outputTokens, 0), - estimatedCostUsd: session.usageRecords.reduce( - (sum, r) => sum + (r.estimatedCostUsd ?? 0), - 0, - ), + let inputTokens = 0 + let outputTokens = 0 + let estimatedCostUsd = 0 + + for (const r of session.usageRecords) { + inputTokens += r.inputTokens + outputTokens += r.outputTokens + estimatedCostUsd += r.estimatedCostUsd ?? 0 } + + return { inputTokens, outputTokens, estimatedCostUsd } } function mapSessionItem(session: SessionWithInclude): SessionItem { diff --git a/packages/web/src/lib/server/weekly-report.ts b/packages/web/src/lib/server/weekly-report.ts index ace2f44..b18bb4c 100644 --- a/packages/web/src/lib/server/weekly-report.ts +++ b/packages/web/src/lib/server/weekly-report.ts @@ -446,17 +446,18 @@ export async function getWeeklyReport( } // Insights — delegation - const totalAgentCalls = thisWeekRollups.reduce( - (sum, r) => sum + Object.values(r.agentCounts).reduce((a, b) => a + b, 0), - 0, - ) - const totalSkillCalls = thisWeekRollups.reduce( - (sum, r) => sum + Object.values(r.skillCounts).reduce((a, b) => a + b, 0), - 0, - ) + let totalAgentCalls = 0 + let totalSkillCalls = 0 const distinctSkillsThisWeek = new Set() + for (const r of thisWeekRollups) { - for (const k of Object.keys(r.skillCounts)) distinctSkillsThisWeek.add(k) + for (const count of Object.values(r.agentCounts)) { + totalAgentCalls += count + } + for (const [skillName, count] of Object.entries(r.skillCounts)) { + totalSkillCalls += count + distinctSkillsThisWeek.add(skillName) + } } const insights: WeeklyInsights = {