perf: fix N+1 query in swarm status blocked check (bd-7p5l)
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 <noreply@anthropic.com>
This commit is contained in:
@@ -614,7 +614,6 @@ Examples:
|
|||||||
|
|
||||||
// getSwarmStatus computes current swarm status from beads.
|
// getSwarmStatus computes current swarm status from beads.
|
||||||
func getSwarmStatus(ctx context.Context, s interface {
|
func getSwarmStatus(ctx context.Context, s interface {
|
||||||
GetIssue(context.Context, string) (*types.Issue, error)
|
|
||||||
GetDependents(context.Context, string) ([]*types.Issue, error)
|
GetDependents(context.Context, string) ([]*types.Issue, error)
|
||||||
GetDependencyRecords(context.Context, string) ([]*types.Dependency, error)
|
GetDependencyRecords(context.Context, string) ([]*types.Dependency, error)
|
||||||
}, epic *types.Issue) (*SwarmStatus, error) {
|
}, epic *types.Issue) (*SwarmStatus, error) {
|
||||||
@@ -659,6 +658,12 @@ func getSwarmStatus(ctx context.Context, s interface {
|
|||||||
childIDSet[issue.ID] = true
|
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)
|
// Build dependency map (within epic children only)
|
||||||
dependsOn := make(map[string][]string)
|
dependsOn := make(map[string][]string)
|
||||||
for _, issue := range childIssues {
|
for _, issue := range childIssues {
|
||||||
@@ -700,12 +705,11 @@ func getSwarmStatus(ctx context.Context, s interface {
|
|||||||
status.Active = append(status.Active, si)
|
status.Active = append(status.Active, si)
|
||||||
|
|
||||||
default: // open or other
|
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]
|
deps := dependsOn[issue.ID]
|
||||||
var blockers []string
|
var blockers []string
|
||||||
for _, depID := range deps {
|
for _, depID := range deps {
|
||||||
depIssue, _ := s.GetIssue(ctx, depID)
|
if depStatus, ok := statusMap[depID]; ok && depStatus != types.StatusClosed {
|
||||||
if depIssue != nil && depIssue.Status != types.StatusClosed {
|
|
||||||
blockers = append(blockers, depID)
|
blockers = append(blockers, depID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user