fix: prevent infinite loop in compute_scheduling_scores with circular deps

Add visited set to BFS algorithm to handle circular dependencies gracefully.
Previously, cycles in the dependency graph caused the orchestrator to hang
at 100% CPU indefinitely during startup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rudiheydra
2026-01-27 09:08:25 +11:00
parent 910ca34eac
commit d68d70c800

View File

@@ -300,15 +300,20 @@ def compute_scheduling_scores(features: list[dict]) -> dict[int, float]:
parents[f["id"]].append(dep_id) parents[f["id"]].append(dep_id)
# Calculate depths via BFS from roots # Calculate depths via BFS from roots
# Use visited set to prevent infinite loops from circular dependencies
depths: dict[int, int] = {} depths: dict[int, int] = {}
visited: set[int] = set()
roots = [f["id"] for f in features if not parents[f["id"]]] roots = [f["id"] for f in features if not parents[f["id"]]]
queue = [(root, 0) for root in roots] queue = [(root, 0) for root in roots]
while queue: while queue:
node_id, depth = queue.pop(0) node_id, depth = queue.pop(0)
if node_id not in depths or depth > depths[node_id]: if node_id in visited:
depths[node_id] = depth continue # Skip already visited nodes (handles cycles)
visited.add(node_id)
depths[node_id] = depth
for child_id in children[node_id]: for child_id in children[node_id]:
queue.append((child_id, depth + 1)) if child_id not in visited:
queue.append((child_id, depth + 1))
# Handle orphaned nodes (shouldn't happen but be safe) # Handle orphaned nodes (shouldn't happen but be safe)
for f in features: for f in features: