From 3fd4eccb78a16310f4c8b5e36b11fe1c8cb3289c Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Sun, 28 Dec 2025 21:35:09 -0800 Subject: [PATCH] perf: fix N+1 query in swarm status blocked check (bd-7p5l) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build status map upfront from childIssues instead of calling GetIssue for each dependency. Reduces queries from O(issues * deps) to O(issues). Also removes unused GetIssue from the interface. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- cmd/bd/swarm.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd/bd/swarm.go b/cmd/bd/swarm.go index 7da808f4..913174fa 100644 --- a/cmd/bd/swarm.go +++ b/cmd/bd/swarm.go @@ -614,7 +614,6 @@ Examples: // getSwarmStatus computes current swarm status from beads. func getSwarmStatus(ctx context.Context, s interface { - GetIssue(context.Context, string) (*types.Issue, error) GetDependents(context.Context, string) ([]*types.Issue, error) GetDependencyRecords(context.Context, string) ([]*types.Dependency, error) }, epic *types.Issue) (*SwarmStatus, error) { @@ -659,6 +658,12 @@ func getSwarmStatus(ctx context.Context, s interface { childIDSet[issue.ID] = true } + // Build status map for efficient blocked checks (avoids N+1 queries) + statusMap := make(map[string]types.Status) + for _, issue := range childIssues { + statusMap[issue.ID] = issue.Status + } + // Build dependency map (within epic children only) dependsOn := make(map[string][]string) for _, issue := range childIssues { @@ -700,12 +705,11 @@ func getSwarmStatus(ctx context.Context, s interface { status.Active = append(status.Active, si) default: // open or other - // Check if blocked by open dependencies + // Check if blocked by open dependencies (uses statusMap, no extra queries) deps := dependsOn[issue.ID] var blockers []string for _, depID := range deps { - depIssue, _ := s.GetIssue(ctx, depID) - if depIssue != nil && depIssue.Status != types.StatusClosed { + if depStatus, ok := statusMap[depID]; ok && depStatus != types.StatusClosed { blockers = append(blockers, depID) } }