From ee09c2f4d2e89d1eb755a63012692cc21651f7f5 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 31 May 2026 21:35:49 +0000 Subject: [PATCH 1/3] feat(perf): replace multiple array iterations with single loop - Replaces chained `.reduce()` and `.map()` calls with single `for` loops in session API routes - Reduces iteration overhead from O(3N)/O(4N) to O(N) over Prisma include payloads - Logs critical learning to `.jules/bolt.md` --- .jules/bolt.md | 3 ++ .../dashboard/sessions/[sessionId]/route.ts | 33 ++++++++++++------- .../[orgSlug]/dashboard/sessions/route.ts | 19 +++++++---- 3 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..5d0a7f5 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-06-01 - Consolidate Multiple Iterations Over Prisma Include Datasets +**Learning:** Chained array methods like `.reduce()` and `.map()` on relations loaded via Prisma `include` clauses cause unnecessary performance overhead due to multiple passes over the same dataset. This becomes a measurable bottleneck when the relation returns a large number of records (e.g., `usageRecords` on `session` data). +**Action:** Replace multiple functional iteration calls over relation sets loaded via `include` with a single, efficient `for` loop to compute all derived metrics and transformed arrays simultaneously. 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..2e4894a 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,18 +43,27 @@ 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) - - const usageTimeline: SessionTimelineUsage[] = session.usageRecords.map((r) => ({ - timestamp: r.timestamp.toISOString(), - inputTokens: r.inputTokens, - outputTokens: r.outputTokens, - estimatedCostUsd: r.estimatedCostUsd ?? 0, - model: r.model, - isSubagent: r.isSubagent, - })) + // ⚡ Bolt Optimization: Replace 3 .reduce() calls and 1 .map() with a single loop + // Reduces O(4N) array passes into O(N) iteration, saving CPU cycles on large payloads + let totalInput = 0 + let totalOutput = 0 + let totalCost = 0 + const usageTimeline: SessionTimelineUsage[] = new Array(session.usageRecords.length) + + for (let i = 0; i < session.usageRecords.length; i++) { + const r = session.usageRecords[i] + totalInput += r.inputTokens + totalOutput += r.outputTokens + totalCost += r.estimatedCostUsd ?? 0 + usageTimeline[i] = { + timestamp: r.timestamp.toISOString(), + inputTokens: r.inputTokens, + outputTokens: r.outputTokens, + estimatedCostUsd: r.estimatedCostUsd ?? 0, + model: r.model, + isSubagent: r.isSubagent, + } + } // 각 UsageRecord를 "직전 ASSISTANT 턴"에 귀속시켜 메시지별 토큰/비용/모델 집계. // TOOL 메시지는 건너뛰고 가장 가까운 선행 ASSISTANT로 타고 올라감. 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..e222445 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,19 @@ 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, - ), + // ⚡ Bolt Optimization: Use a single loop instead of 3 array reductions + // Reduces iteration overhead from O(3N) to O(N) + 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 { From f197403aed89efed92a417d8c697c456731c98c2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 1 Jun 2026 20:29:53 +0900 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20.jules/bolt.md=20AI=20=EC=97=90?= =?UTF-8?q?=EC=9D=B4=EC=A0=84=ED=8A=B8=20=EB=82=B4=EB=B6=80=20=EB=85=B8?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI 에이전트 내부 로그 파일은 저장소에 커밋되어서는 안 됩니다. Co-Authored-By: Mastra Code (anthropic/claude-opus-4-6) --- .jules/bolt.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md deleted file mode 100644 index 5d0a7f5..0000000 --- a/.jules/bolt.md +++ /dev/null @@ -1,3 +0,0 @@ -## 2024-06-01 - Consolidate Multiple Iterations Over Prisma Include Datasets -**Learning:** Chained array methods like `.reduce()` and `.map()` on relations loaded via Prisma `include` clauses cause unnecessary performance overhead due to multiple passes over the same dataset. This becomes a measurable bottleneck when the relation returns a large number of records (e.g., `usageRecords` on `session` data). -**Action:** Replace multiple functional iteration calls over relation sets loaded via `include` with a single, efficient `for` loop to compute all derived metrics and transformed arrays simultaneously. From 15361278d3aef636b8fde2eabd542eabd16efba2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 1 Jun 2026 20:30:45 +0900 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20AI=20=EC=97=90=EC=9D=B4=EC=A0=84?= =?UTF-8?q?=ED=8A=B8=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 불필요한 Bolt Optimization 주석을 제거합니다. Co-Authored-By: Mastra Code (anthropic/claude-opus-4-6) --- .../api/orgs/[orgSlug]/dashboard/sessions/[sessionId]/route.ts | 2 -- .../web/src/app/api/orgs/[orgSlug]/dashboard/sessions/route.ts | 2 -- 2 files changed, 4 deletions(-) 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 2e4894a..1151f08 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,8 +43,6 @@ export async function GET( return forbiddenByRole(access.role, '본인 세션만 열람 가능') } - // ⚡ Bolt Optimization: Replace 3 .reduce() calls and 1 .map() with a single loop - // Reduces O(4N) array passes into O(N) iteration, saving CPU cycles on large payloads let totalInput = 0 let totalOutput = 0 let totalCost = 0 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 e222445..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,8 +33,6 @@ const sessionInclude = { type SessionWithInclude = Prisma.ClaudeSessionGetPayload<{ include: typeof sessionInclude }> function getSessionTotals(session: SessionWithInclude) { - // ⚡ Bolt Optimization: Use a single loop instead of 3 array reductions - // Reduces iteration overhead from O(3N) to O(N) let inputTokens = 0 let outputTokens = 0 let estimatedCostUsd = 0