This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch maven-resolver-1.9.x
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/maven-resolver-1.9.x by this 
push:
     new 1811ec7e8 [1.9.x] Maven resolver lock issue reproducer (#1664)
1811ec7e8 is described below

commit 1811ec7e886b787b5c29983b42360a5cebcfaa9d
Author: Tamas Cservenak <[email protected]>
AuthorDate: Mon Nov 17 20:36:33 2025 +0100

    [1.9.x] Maven resolver lock issue reproducer (#1664)
    
    Lock issue reproducer. It does not run as part of test/build, is meant to 
be ad-hoc ran from IDE.
---
 .../ResolveTransitiveDependenciesParallel.java     | 239 +++++++++++++++++++++
 1 file changed, 239 insertions(+)

diff --git 
a/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java
 
b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java
new file mode 100644
index 000000000..c5825b6a1
--- /dev/null
+++ 
b/maven-resolver-demos/maven-resolver-demo-snippets/src/main/java/org/apache/maven/resolver/examples/ResolveTransitiveDependenciesParallel.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.resolver.examples;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.maven.resolver.examples.util.Booter;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.util.artifact.JavaScopes;
+
+/**
+ * Resolves the transitive (compile) LARGE dependencies of an imaginary 
artifact in parallel.
+ * This is the reproducer for locking issues: <a 
href="https://github.com/apache/maven-resolver/issues/1644>GH-1644</a>
+ * This code does NOT run as part of build/tests, it is meant to be ad-hoc run 
from IDE or alike.
+ */
+public class ResolveTransitiveDependenciesParallel {
+
+    /**
+     * Main.
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String[] args) throws Exception {
+        
System.out.println("------------------------------------------------------------");
+        
System.out.println(ResolveTransitiveDependencies.class.getSimpleName());
+
+        RepositorySystem system = 
Booter.newRepositorySystem(Booter.selectFactory(args));
+
+        // note: these numbers below are not "universal", they stand for one 
given WS with one given network,
+        // and they may need change with time if anything changes in relation 
(even remote like Central!)
+        //
+        // cstamas (DK HW+net) 17. 11. 2025 (w/ empty local repo)
+        // One job is done in 20 sec
+        // BUT other must wait as they are serialized (time adds up)
+        // reproducer to succeed: 210 sec
+        // my run:
+        // DONE (21 sec): org.example:test:1: resolved 11; failed 0
+        // DONE (37 sec): org.example:test:6: resolved 11; failed 0
+        // DONE (60 sec): org.example:test:4: resolved 11; failed 0
+        // DONE (60 sec): org.example:test:5: resolved 11; failed 0
+        // DONE (170 sec): org.example:test:8: resolved 11; failed 0
+        // DONE (181 sec): org.example:test:3: resolved 11; failed 0
+        // DONE (181 sec): org.example:test:7: resolved 11; failed 0
+        // DONE (181 sec): org.example:test:2: resolved 11; failed 0
+        // =====
+        // TOTAL success=8; fail=0
+        //
+        // Pattern: as said above, one job does in 20 sec, BUT subsequent one 
will do it in cca 40 sec (waiting 20 sec)
+        // and so on, the times are adding up. Each subsequent job with start 
by waiting for previous jobs to finish
+        // due (intentional) artifact overlaps.
+
+        DefaultRepositorySystemSession session = 
Booter.newRepositorySystemSession(system);
+        session.setConfigProperty("aether.syncContext.named.time", "210");
+        session.setTransferListener(null);
+        session.setRepositoryListener(null);
+
+        Artifact bigArtifact1 = new 
DefaultArtifact("org.bytedeco:llvm:jar:linux-arm64:16.0.4-1.5.9");
+        Artifact bigArtifact2 = new 
DefaultArtifact("org.bytedeco:llvm:jar:linux-armhf:16.0.4-1.5.9");
+        Artifact bigArtifact3 = new 
DefaultArtifact("org.bytedeco:llvm:jar:linux-ppc64le:16.0.4-1.5.9");
+        Artifact bigArtifact4 = new 
DefaultArtifact("org.bytedeco:llvm:jar:linux-x86:16.0.4-1.5.9");
+        Artifact bigArtifact5 = new 
DefaultArtifact("org.bytedeco:llvm:jar:linux-x86_64:16.0.4-1.5.9");
+        Artifact bigArtifact6 = new 
DefaultArtifact("org.bytedeco:llvm:jar:macosx-arm64:16.0.4-1.5.9");
+        Artifact bigArtifact7 = new 
DefaultArtifact("org.bytedeco:llvm:jar:macosx-x86_64:16.0.4-1.5.9");
+        Artifact bigArtifact8 = new 
DefaultArtifact("org.bytedeco:llvm:jar:windows-x86:16.0.4-1.5.9");
+        Artifact bigArtifact9 = new 
DefaultArtifact("org.bytedeco:llvm:jar:windows-x86_64:16.0.4-1.5.9");
+
+        CountDownLatch latch = new CountDownLatch(8);
+        AtomicInteger success = new AtomicInteger(0);
+        AtomicInteger fail = new AtomicInteger(0);
+
+        Thread thread1 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:1",
+                bigArtifact1,
+                bigArtifact2));
+        Thread thread2 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:2",
+                bigArtifact2,
+                bigArtifact3));
+        Thread thread3 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:3",
+                bigArtifact3,
+                bigArtifact4));
+        Thread thread4 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:4",
+                bigArtifact4,
+                bigArtifact5));
+        Thread thread5 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:5",
+                bigArtifact5,
+                bigArtifact6));
+        Thread thread6 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:6",
+                bigArtifact6,
+                bigArtifact7));
+        Thread thread7 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:7",
+                bigArtifact7,
+                bigArtifact8));
+        Thread thread8 = new Thread(resolveWithDependencies(
+                latch,
+                success,
+                fail,
+                system,
+                session,
+                Booter.newRepositories(system, session),
+                "org.example:test:8",
+                bigArtifact8,
+                bigArtifact9));
+
+        thread1.start();
+        thread2.start();
+        thread3.start();
+        thread4.start();
+        thread5.start();
+        thread6.start();
+        thread7.start();
+        thread8.start();
+
+        latch.await();
+
+        System.out.println("=====");
+        System.out.println("TOTAL success=" + success.get() + "; fail=" + 
fail.get());
+    }
+
+    @SuppressWarnings("checkstyle:parameternumber")
+    private static Runnable resolveWithDependencies(
+            CountDownLatch latch,
+            AtomicInteger success,
+            AtomicInteger fail,
+            RepositorySystem system,
+            RepositorySystemSession session,
+            List<RemoteRepository> repositories,
+            String gav,
+            Artifact... deps) {
+        return () -> {
+            try {
+                Instant now = Instant.now();
+                CollectRequest collectRequest = new CollectRequest();
+                collectRequest.setRootArtifact(new DefaultArtifact(gav));
+                for (Artifact dep : deps) {
+                    collectRequest.addDependency(new Dependency(dep, 
JavaScopes.COMPILE));
+                }
+                collectRequest.setRepositories(repositories);
+                DependencyRequest dependencyRequest = new 
DependencyRequest(collectRequest, null);
+                List<ArtifactResult> artifactResults =
+                        system.resolveDependencies(session, 
dependencyRequest).getArtifactResults();
+                int resolved = 9;
+                int fails = 0;
+                for (ArtifactResult artifactResult : artifactResults) {
+                    if (artifactResult.isResolved()) {
+                        resolved++;
+                    } else {
+                        fails++;
+                    }
+                }
+                String dur = Duration.between(now, 
Instant.now()).get(ChronoUnit.SECONDS) + " sec";
+                System.out.println("DONE (" + dur + "): " + gav + ": resolved 
" + resolved + "; failed " + fails);
+                success.getAndIncrement();
+            } catch (Exception e) {
+                System.out.println("FAILED " + gav + ": " + e.getMessage());
+                fail.getAndIncrement();
+            } finally {
+                latch.countDown();
+            }
+        };
+    }
+}

Reply via email to