Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(npm): improve peer dependency resolution with circular dependencies #18069

Merged
merged 15 commits into from
Mar 8, 2023

Conversation

dsherret
Copy link
Member

@dsherret dsherret commented Mar 7, 2023

This improves peer dependency resolution yet again. We did not handle scenarios like the following:

// a -> b -> c -> d -> c -> b (peer)

...which would maybe work ok the first time its run in some cases, but then lead to a lockfile that would error on load.

This now keeps track of circular dependencies and updates nodes accordingly. That said, there is still a lurking bug in this code somewhere that I've added a comment for (there is a mitigation on the tail end that seems to work well). The current state is much better than before and I can look into it later. I think it's something small that's incorrect.

cli/npm/resolution/graph.rs Show resolved Hide resolved
nv: Arc<NpmPackageNv>,
/// Descendants in the path that circularly link to an ancestor in a child.These
/// descendants should be kept up to date and always point to this node.
linked_circular_descendants: Mutex<Vec<Arc<GraphPath>>>,
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the new concept here. We keep track of descendants that have this ancestor as a child.

@@ -1329,40 1465,30 @@ mod test {
assert_eq!(
packages,
vec![
NpmResolutionPackage {
pkg_id: NpmPackageId::from_serialized("[email protected]").unwrap(),
TestNpmResolutionPackage {
Copy link
Member Author

Choose a reason for hiding this comment

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

Below this point is mostly updates to use a new less verbose struct for testing. At the bottom of this file and line 3124 there are some new tests. I have commented where those are.

@@ -3377,6 3120,100 @@ mod test {
);
}

#[tokio::test]
async fn resolve_peer_deps_in_ancestor_root() {
Copy link
Member Author

Choose a reason for hiding this comment

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

New tests here.

Copy link
Member

Choose a reason for hiding this comment

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

Nice, these indeed look tricky

@@ -3614,10 3411,254 @@ mod test {
);
}

#[tokio::test]
Copy link
Member Author

Choose a reason for hiding this comment

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

New tests here and below.

std::env::var("DENO_UNSTABLE_NPM_SYNC_DOWNLOAD").is_ok()
// this gets called a lot when doing npm resolution and was taking
// a significant amount of time, so cache it in a lazy
*SHOULD_SYNC_DOWNLOAD
Copy link
Member Author

Choose a reason for hiding this comment

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

Before: 8.6% of execution -- After: 0%


if !found_peer {
found_peer = !self.graph.borrow_node_mut(child_id).no_peers;
// cache all the dependencies' registry infos in parallel if should
Copy link
Member

Choose a reason for hiding this comment

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

This comment makes no sense :(

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure how to reword this because it's saying what the next line does

Comment on lines 3478 to 3479
// a -> b -> c -> d -> c where c has a peer dependency on b
// -> e -> f -> d -> c where f has a peer dep on a
Copy link
Member

Choose a reason for hiding this comment

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

🫠

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

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

LGTM, see comment about Arc

@dsherret dsherret merged commit 23e1ba7 into denoland:main Mar 8, 2023
@dsherret dsherret deleted the fix_improve_peer_deps_more branch March 8, 2023 17:22
kt3k pushed a commit that referenced this pull request Mar 10, 2023
…es (#18069)

This improves peer dependency resolution yet again. We did not handle
scenarios like the following:

```
// a -> b -> c -> d -> c -> b (peer)
```

...which would maybe work ok the first time its run in some cases, but
then lead to a lockfile that would error on load.

This now keeps track of circular dependencies and updates nodes
accordingly. That said, there is still a lurking bug in this code
somewhere that I've added a comment for (there is a mitigation on the
tail end that seems to work well). The current state is much better than
before and I can look into it later. I think it's something small that's
incorrect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants