-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(#9673): break mutual-wait dead-lock introduced in #8760 #9675
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
Conversation
💖 Thanks for opening this pull request! 💖 |
If you are saying the cycle is not detected because the real package name is not taken into account, then won't this fix the issue? const node = ctx.dependenciesTree.get(childNodeId)!
graph.push([node.resolvedPackage.name, edges])
graph.push([currentAlias, edges]) |
I tried applying the suggested change locally, but unfortunately it doesn't seem to resolve the issue. Running a reproducible case still results in the same error that was originally fixed by #8760: diff --git a/pkg-manager/resolve-dependencies/src/resolvePeers.ts b/pkg-manager/resolve-dependencies/src/resolvePeers.ts
index 07830ddd1..77b19dddb 100644
--- a/pkg-manager/resolve-dependencies/src/resolvePeers.ts
+++ b/pkg-manager/resolve-dependencies/src/resolvePeers.ts
@@ -844,6 +844,8 @@ async function resolvePeersOfChildren<T extends PartialResolvedPackage> (
allResolvedPeers.set(peerName, peerNodeId)
edges.push(peerName)
}
+ const node = ctx.dependenciesTree.get(childNodeId)!
+ graph.push([node.resolvedPackage.name, edges])
graph.push([currentAlias, edges])
for (const [missingPeer, range] of missingPeers.entries()) {
allMissingPeers.set(missingPeer, range)
The issue seems to involve a peer layout where an alias and the actual package name depend on each other. Since only one directional edge is retained in the graph, graph-cycles doesn't detect the cycle, and both sides end up mutually waiting. That said, I'm not deeply familiar with the overall structure of the pnpm codebase, so it's very possible I'm missing something. Thanks for taking a look! |
This should work then const node = ctx.dependenciesTree.get(childNodeId)!
graph.push([node.resolvedPackage.name, edges])
if (currentAlias !== node.resolvedPackage.name) {
graph.push([currentAlias, edges])
} It would be really good to cover this with a test. Can you share the reproduction? If it uses private packages, we can simulate the same dependency graph with our registry mock: https://github.com/pnpm/registry-mock |
That doesn't work either.
|
I successfully used How should I provide this reproduction? Is there any guideline I should follow? |
Here's the reproduction repo: https://github.com/reekystive/pnpm-peers-deadlock-issue |
Submit your packages to the registry-mock repository, then I'll publish it and you'll be able to write a test for it in this PR. |
I am adding the test |
Congrats on merging your first pull request! 🎉🎉🎉 |
Thanks for fixing this! Our team relies heavily on pnpm every day, thank you for all the hard work and thoughtful design that make it such a dependable tool. We’re very grateful! ❤️ |
close #9673 --------- Co-authored-by: Zoltan Kochan <[email protected]>
Thanks for providing the reproduction packages. Without that it is really hard to fix such issues. |
The Issue
npm:
alias.graph-cycles
does not report a cycle.pnpm install
hangs (see Installation hangs indefinitely when resolving peers in pnpm 9.13.2 – 10.12.1 (regression of #8760) #9673).Changes
ExtendedDeferred
Populate metadata
Deferred
, attachalias
('unknown'
is fine until we meet the real one) and an emptywaitingFor
set.pendingPeers
, copy those aliases into its ownwaitingFor
.Mutual-wait detection in
calculateDepPath()
This breaks 2-node (or longer) dead-locks without relying on the graph.
Keep existing cycle handling (
cyclicPeerAliases
) for larger cycles.Cleanup
debugLog
/DEBUG_PEERS
code.Impact
Tests
Related