Fix pipeline deadlock on cross-team task dependencies#697
Merged
Iron-Ham merged 1 commit intoMar 21, 2026
Conversation
The decomposer (pipeline.Decompose) grouped tasks into execution teams using only file-affinity via union-find. Tasks with DependsOn relationships but disjoint files landed in separate teams. Since each team's TaskQueue.isClaimable() only resolves dependencies within its own task set, cross-team dependencies were permanently unsatisfiable, deadlocking the pipeline after the first dependency group completed. Fix: union tasks along DependsOn edges in addition to shared-file edges, ensuring all task-level dependencies are resolvable within a single team's queue. Guard against unknown dep IDs to prevent silent union-find corruption via phantom root nodes. Rename groupByFileAffinity -> groupByAffinity to reflect expanded responsibility.
8742241 to
3f7f1e7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pipeline.Decomposegrouped tasks into execution teams using only file-affinity (union-find on shared files). Tasks withDependsOnrelationships but disjoint files landed in separate teams. SinceTaskQueue.isClaimable()only resolves dependencies within its own task set, cross-team dependencies were permanently unsatisfiable — deadlocking the pipeline after the first dependency group completed.DependsOnentries referencing task IDs not in the plan, preventing silent union-find corruption via phantom root nodes.groupByFileAffinity→groupByAffinityto reflect its expanded responsibility (files + dependency edges).Root Cause
The decomposer's union-find only unioned tasks sharing files. When task A (Swift files) and task B (GraphQL files) had no file overlap, they landed in different execution teams. Downstream tasks depending on both A and B were placed in teams where the dep IDs didn't exist in the local
TaskQueue, causingisClaimable()to returnfalsepermanently.Fix
Union tasks along
DependsOnedges in addition to file edges during decomposition. This ensures all task-level dependencies are resolvable within a single team's queue.Test plan
TestDecompose_DependencyGrouping— direct dependency with disjoint files → same teamTestDecompose_TransitiveDependencyGrouping— transitive chain (t3→t2→t1) with disjoint files → all in one teamTestDecompose_DisjointDepsAndFiles— reproduces the exact real-world scenario (swipe framework + GraphQL codegen + wiring task)TestDecompose_UnknownDependencyIgnored— stale dep ID is skipped, no phantom union-find corruptiongo test -race ./...passesgo vet ./...cleangofmt -d .clean