Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix #2013: reuse DependencyManager instance to restore pool cache transparency#2014

Open
gnodet wants to merge 1 commit into
masterapache/maven-resolver:masterfrom
fix/2013apache/maven-resolver:fix/2013Copy head branch name to clipboard
Open

Fix #2013: reuse DependencyManager instance to restore pool cache transparency#2014
gnodet wants to merge 1 commit into
masterapache/maven-resolver:masterfrom
fix/2013apache/maven-resolver:fix/2013Copy head branch name to clipboard

Conversation

@gnodet

@gnodet gnodet commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2013 — BfDependencyCollector pool cache hit/miss changes graph structure (cache-transparency violation).

Root cause: TransitiveDependencyManager.deriveChildManager() always created a new instance (with a unique path field and incrementing depth), making every pool key unique. The BF collector's pool cache includes the DependencyManager in its GraphKey, so distinct-but-semantically-equal managers caused pool misses. On a miss, the GACE-based skipper was consulted and could prune a node's children to zero — even though the same node had children when served from the cache via a different traversal path.

Fix: AbstractDependencyManager.deriveChildManager() now returns this when:

  1. No new management data (versions, scopes, optionals, local paths, exclusions) was collected at the current depth, AND
  2. Management is already being applied (depth >= applyFrom — the isApplied() guard)

The isApplied() guard is critical: at depth < applyFrom, returning this would freeze the depth counter and prevent isApplied() from ever returning true for descendants, breaking management rule application.

This optimization addresses the common case for transitive dependencies whose POMs do not declare <dependencyManagement>. ClassicDependencyManager (Maven 3.x) was not affected because its deriveUntil=2 caused isDerived() to return this at depth ≥ 2.

Changes

  • AbstractDependencyManager.deriveChildManager() — added instance-reuse optimization before the newInstance() call
  • DependencyManagerTest — new unit test testDeriveChildManagerReusesInstanceWhenNoNewManagementData() verifying the optimization with assertSame/assertNotSame at different depths
  • BfWithSkipperDependencyCollectorTest — new integration test testPoolCacheTransparencyWithTransitiveDependencyManager() with a diamond-like graph (root → b → c → d and root → b-alt → c → d) verifying that c under b-alt retains its children

Test plan

  • Unit test: DependencyManagerTest.testDeriveChildManagerReusesInstanceWhenNoNewManagementData — verifies instance reuse at depth ≥ applyFrom with no management data, and new instance creation otherwise
  • Integration test: BfWithSkipperDependencyCollectorTest.testPoolCacheTransparencyWithTransitiveDependencyManager — end-to-end test demonstrating the bug is fixed
  • All existing tests pass (maven-resolver-util: 447 tests, maven-resolver-impl: 468 tests)

🤖 Generated with Claude Code

…ta is collected

AbstractDependencyManager.deriveChildManager() now returns `this` when no
new management data (versions, scopes, optionals, local paths, exclusions)
was collected at the current depth AND management is already being applied
(depth >= applyFrom). This avoids creating distinct-but-semantically-equal
DependencyManager instances that defeat the BfDependencyCollector pool
cache — the pool key includes the manager, so unique managers cause pool
misses, which lets the skipper prune subtrees that should have been served
from the cache.

The isApplied() guard is necessary: at depth < applyFrom, returning `this`
would freeze the depth counter and prevent management rules from ever being
applied to descendants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
gnodet marked this pull request as ready for review July 24, 2026 23:50
@gnodet
gnodet requested a review from cstamas July 24, 2026 23:50
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.

BfDependencyCollector pool cache hit/miss changes graph structure (cache-transparency violation)

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.