Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adwait1290
Copy link
Contributor

@adwait1290 adwait1290 commented Dec 8, 2025

Current Behavior

In filterAffectedProjects, a new visited Set is created for each touched project:

ctx.touchedProjects.forEach((p) => {
  addAffectedNodes(p, reversed, result, new Set());  // NEW Set per project!
});
ctx.touchedProjects.forEach((p) => {
  addAffectedDependencies(p, reversed, result, new Set());  // NEW Set per project!
});

This defeats the purpose of the visited Set for deduplication. If projects A and B both depend on shared project C, then C gets visited twice.

Expected Behavior

Share a single visited Set across all touched projects:

const visitedNodes = new Set<string>();
const visitedDeps = new Set<string>();
for (const p of ctx.touchedProjects) {
  addAffectedNodes(p, reversed, result, visitedNodes);  // SHARED Set
}
for (const p of ctx.touchedProjects) {
  addAffectedDependencies(p, reversed, result, visitedDeps);  // SHARED Set
}

Performance Impact

Before (separate Sets):              After (shared Sets):
┌─────────────────────────┐         ┌─────────────────────────┐
│  touchedProjects: [A,B] │         │  touchedProjects: [A,B] │
└───────────┬─────────────┘         └───────────┬─────────────┘
            │                                   │
    ┌───────┴───────┐                   ┌───────┴───────┐
    ▼               ▼                   ▼               ▼
┌───────┐       ┌───────┐           ┌───────┐       ┌───────┐
│ A     │       │ B     │           │ A     │       │ B     │
│visited│       │visited│           │       │       │       │
│= {}   │       │= {}   │           │ shared visitedNodes   │
└───┬───┘       └───┬───┘           └───┬───┘       └───┬───┘
    │               │                   │               │
    ▼               ▼                   ▼               ▼
┌───────┐       ┌───────┐           ┌───────────────────────┐
│visit C│       │visit C│           │ visit C (ONCE)        │
│(dup!) │       │(dup!) │           │ skip C from B         │
└───────┘       └───────┘           └───────────────────────┘

Complexity:                         Complexity:
O(touched × shared_deps)            O(total_nodes)

Example: With 50 touched projects sharing 100 common dependencies:

  • Before: 50 × 100 = 5,000 node visits
  • After: ~150 node visits (each node visited once)

Why Accept This PR

  1. Bug-like behavior: The current code defeats the purpose of the visited Set
  2. Significant impact: Affects every nx affected command
  3. Zero risk: Same traversal logic, just shared deduplication
  4. Common scenario: Monorepos often have shared dependencies (utils, types, etc.)

Related Issue(s)

Contributes to #32265

Merge Dependencies

This PR has no dependencies and can be merged independently.


Previously, filterAffectedProjects created a NEW visited Set for each
touched project, defeating the purpose of deduplication. If projects
A and B both depend on shared project C, C would be visited twice.

Now uses shared visited Sets across all touched projects, reducing
redundant traversal from O(touchedProjects × sharedDeps) to O(nodes).
@adwait1290 adwait1290 requested a review from a team as a code owner December 8, 2025 07:28
@netlify
Copy link

netlify bot commented Dec 8, 2025

👷 Deploy request for nx-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 9bf3b58

@vercel
Copy link

vercel bot commented Dec 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nx-dev Ready Ready Preview Dec 10, 2025 7:33am

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@nx-cloud
Copy link
Contributor

nx-cloud bot commented Dec 9, 2025

View your CI Pipeline Execution ↗ for commit 9bf3b58

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 6m 19s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 2m 39s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 12s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-10 09:03:45 UTC

Copy link
Member

@leosvelperez leosvelperez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@leosvelperez leosvelperez changed the title perf(core): share visited Set across affected graph traversal fix(core): share visited Set across affected graph traversal Dec 9, 2025
nx-cloud[bot]

This comment was marked as outdated.

Copy link
Contributor

@nx-cloud nx-cloud bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

A new CI pipeline execution was requested that may update the conclusion below...

Nx Cloud has identified a possible root cause for your failed CI:

Our tests are failing due to an external infrastructure issue: the Foojay resolver service (used by Gradle to provision Java toolchains) is returning 503 Service Temporarily Unavailable errors. The similar-task-failure-detector confirmed this same error exists in the master branch, proving it's unrelated to our PR's changes to affected graph traversal logic. We need to wait for the Foojay service to recover before these e2e tests can pass.

No code changes were suggested for this issue.

If the issue was transient, you can trigger a rerun by pushing an empty commit:

git commit --allow-empty -m "chore: trigger rerun"
git push

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

@leosvelperez leosvelperez merged commit badc998 into nrwl:master Dec 10, 2025
15 of 18 checks passed
FrozenPandaz pushed a commit that referenced this pull request Dec 15, 2025
## Current Behavior

In `filterAffectedProjects`, a **new visited Set is created for each
touched project**:

```typescript
ctx.touchedProjects.forEach((p) => {
  addAffectedNodes(p, reversed, result, new Set());  // NEW Set per project!
});
ctx.touchedProjects.forEach((p) => {
  addAffectedDependencies(p, reversed, result, new Set());  // NEW Set per project!
});
```

This defeats the purpose of the visited Set for deduplication. If
projects A and B both depend on shared project C, then C gets visited
**twice**.

## Expected Behavior

Share a single visited Set across all touched projects:

```typescript
const visitedNodes = new Set<string>();
const visitedDeps = new Set<string>();
for (const p of ctx.touchedProjects) {
  addAffectedNodes(p, reversed, result, visitedNodes);  // SHARED Set
}
for (const p of ctx.touchedProjects) {
  addAffectedDependencies(p, reversed, result, visitedDeps);  // SHARED Set
}
```

## Performance Impact

```
Before (separate Sets):              After (shared Sets):
┌─────────────────────────┐         ┌─────────────────────────┐
│  touchedProjects: [A,B] │         │  touchedProjects: [A,B] │
└───────────┬─────────────┘         └───────────┬─────────────┘
            │                                   │
    ┌───────┴───────┐                   ┌───────┴───────┐
    ▼               ▼                   ▼               ▼
┌───────┐       ┌───────┐           ┌───────┐       ┌───────┐
│ A     │       │ B     │           │ A     │       │ B     │
│visited│       │visited│           │       │       │       │
│= {}   │       │= {}   │           │ shared visitedNodes   │
└───┬───┘       └───┬───┘           └───┬───┘       └───┬───┘
    │               │                   │               │
    ▼               ▼                   ▼               ▼
┌───────┐       ┌───────┐           ┌───────────────────────┐
│visit C│       │visit C│           │ visit C (ONCE)        │
│(dup!) │       │(dup!) │           │ skip C from B         │
└───────┘       └───────┘           └───────────────────────┘

Complexity:                         Complexity:
O(touched × shared_deps)            O(total_nodes)
```

**Example**: With 50 touched projects sharing 100 common dependencies:
- Before: 50 × 100 = 5,000 node visits
- After: ~150 node visits (each node visited once)

## Why Accept This PR

1. **Bug-like behavior**: The current code defeats the purpose of the
visited Set
2. **Significant impact**: Affects every `nx affected` command
3. **Zero risk**: Same traversal logic, just shared deduplication
4. **Common scenario**: Monorepos often have shared dependencies (utils,
types, etc.)
## Related Issue(s)

Contributes to #32265

## Merge Dependencies

This PR has no dependencies and can be merged independently.

---

Co-authored-by: Leosvel Pérez Espinosa <[email protected]>
@github-actions
Copy link
Contributor

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants