Skip to content

Tune Maven's own retry/concurrency to reduce Maven Central rate-limiting - #1835

Open
ramakrishnap-nv wants to merge 3 commits into
mainfrom
java-maven-retry-config
Open

Tune Maven's own retry/concurrency to reduce Maven Central rate-limiting#1835
ramakrishnap-nv wants to merge 3 commits into
mainfrom
java-maven-retry-config

Conversation

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

Summary

  • java-static-test (from Explore self-contained Java classifier JARs with a statically linked libcuopt #1818) and, less often, java-build have hit 429 Too Many Requests from Maven Central while resolving plugins like maven-source-plugin on a cold repository. cuopt_mvn's retry loop (fixed in Fix cuopt_mvn retry loop being silently skipped under set -e #1823 to actually run under set -e) retries the whole mvn invocation with backoff, but that's compensating for Maven's own resolver never being tuned for CI -- 4 attempts don't reliably outlast a sustained rate-limit window, and by the time the outer wrapper retries, the burst of parallel requests that likely triggered the 429 in the first place repeats.
  • cuDF and cuVS already carry a fix for this exact problem in their own Java/Maven builds: a project-level .mvn/maven.config, auto-applied to every mvn invocation with no wrapper script needed, that caps concurrent downloads and adds a real backoff inside Maven's own transport-layer retry handler.

Fix

Add java/cuopt/.mvn/maven.config, matching cuDF's (java/.mvn/maven.config) and cuVS's (java/cuvs-java/.mvn/maven.config) content exactly:

-e
-B
-Daether.connector.basic.downstreamThreads=1
-Daether.transport.http.retryHandler.count=5
-Daether.transport.http.retryHandler.interval=10000
-Dmaven.wagon.http.retryHandler.count=5
  • aether.connector.basic.downstreamThreads=1 caps Maven's own concurrent download threads, reducing the burst of parallel requests against Maven Central that likely triggers the rate-limiting in the first place.
  • aether.transport.http.retryHandler.interval=10000 adds a real 10s backoff inside Maven's own resolver, at the transport layer.

cuopt_mvn's existing -D flags (java/cuopt/scripts/maven.sh) target the connector-layer retry handler (aether.connector.http.retryHandler.*), which recent Maven resolver versions may no longer consult now that retry logic lives at the transport layer -- this adds the layer that actually gets read. Verified via:

mvn org.apache.maven.plugins:maven-help-plugin:3.4.0:evaluate \
  -Dexpression=aether.transport.http.retryHandler.interval -q -DforceStdout
# -> 10000

cuopt_mvn's outer shell-level retry loop is left in place as a second layer -- it's still useful for failures Maven's own retry can't cover (network drops mid-request, etc).

Test plan

  • Confirmed the property resolves correctly via maven-help-plugin:evaluate (see above).
  • Ran the full packaged-jar-tests Maven Java suite locally with this config present; passes cleanly.
  • java-build and java-static-test CI run clean without hitting Maven Central 429s.

Split out of #1818, where this was found while investigating an unrelated flaky Surefire crash -- this fix is independently useful for the existing java-build job today, not specific to that PR's self-contained classifier JAR work.

java-static-test has repeatedly hit 429 Too Many Requests resolving
plugins like maven-source-plugin from a cold repository -- the
cuopt_mvn wrapper's retry loop (fixed in #1823) retries the whole mvn
invocation with backoff, but that's compensating for Maven's own
resolver never being tuned, and 4 attempts don't reliably outlast a
sustained rate limit.

cuDF and cuVS already carry this exact fix for their own Java/Maven
Central builds: a project-level .mvn/maven.config (auto-applied to
every mvn invocation, no wrapper needed) that caps concurrent
downloads to reduce burst request rate and adds a real backoff inside
Maven's own transport-layer retry handler, rather than only retrying
around the outside of a failed process:

  -Daether.connector.basic.downstreamThreads=1
  -Daether.transport.http.retryHandler.count=5
  -Daether.transport.http.retryHandler.interval=10000
  -Dmaven.wagon.http.retryHandler.count=5

cuopt_mvn's own -D flags target the connector-layer retry handler,
which recent Maven resolver versions may no longer consult now that
retry logic lives at the transport layer -- this adds the layer that
actually gets read, verified via `mvn help:evaluate
-Dexpression=aether.transport.http.retryHandler.interval` resolving
to 10000. Verified the packaged-jar-tests suite still passes with
this config present.
@ramakrishnap-nv
ramakrishnap-nv requested a review from a team as a code owner September 1, 2026 13:29
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 381d7698-645f-4cdd-80d8-1eff3d3a8313

📥 Commits

Reviewing files that changed from the base of the PR and between e2facf8 and af54fa7.

📒 Files selected for processing (1)
  • java/cuopt/pom.xml

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

The Java build now runs Maven from java/cuopt, which enables module-local Maven settings. Source and Javadoc JAR attachment runs only when the attach-source-javadoc profile is explicitly activated.

Changes

Maven configuration

Layer / File(s) Summary
Maven execution and retry settings
java/cuopt/.mvn/maven.config, build.sh
The build enters java/cuopt before invoking the relative pom.xml. Maven configuration enables error output, batch mode, one downstream connector thread, five retries, and a 10-second retry interval.
Source and Javadoc attachment profile
java/cuopt/pom.xml
The POM places source and Javadoc plugin executions in the attach-source-javadoc profile. Javadoc doclint remains disabled for that profile.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to af54f

The PR only tunes Maven download concurrency and retry backoff; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: iroy30, gforsyth

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the Maven retry, concurrency, and plugin-resolution changes. It also documents verification and pending CI validation.
Title check ✅ Passed The title is concise, specific, and directly describes the primary Maven retry and concurrency changes intended to reduce Maven Central rate-limiting.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch java-maven-retry-config

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

CI Test Summary

✅ 21 passed · 10 cancelled / not completed

@ramakrishnap-nv ramakrishnap-nv self-assigned this Sep 1, 2026
@ramakrishnap-nv ramakrishnap-nv added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels Sep 1, 2026
java/cuopt/.mvn/maven.config is only auto-discovered when Maven's
directory search (which walks up from the current working directory,
not from -f's directory) reaches java/cuopt. build.sh invoked
cuopt_mvn with -f but never changed into that directory, so the
transport-layer retry/backoff settings added for the Maven Central
429 rate-limiting never took effect. test.sh already cd's into
MODULE_DIR for the same reason; mirror that here, matching how cuDF
cd's into java/ before its mvn calls for the same .mvn/maven.config.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ramakrishnap-nv
ramakrishnap-nv requested a review from a team as a code owner September 1, 2026 15:10
…y mvn test/verify

maven-source-plugin and maven-javadoc-plugin were declared
unconditionally in <build><plugins>, so every `mvn test`/`verify`
invocation -- including ci/test_java.sh's, which never packages
anything for publishing -- still had to resolve
maven-source-plugin:3.3.1 from Maven Central on every run. That's the
same artifact that's repeatedly failed on 429 in the java-static-test
investigation on #1818, and there's no reason java-build's plain test
path should pay for it either.

No script on this branch currently packages a JAR for real
publishing (only java/cuopt/scripts/test.sh's `mvn verify`, for
testing, and build.sh's `mvn clean package`, for local dev -- neither
needs sources/javadoc jars), so nothing needs the new
attach-source-javadoc profile activated; this is a pure reduction in
unnecessary Maven Central resolution.

Verified locally: `mvn compile` no longer resolves
maven-source-plugin/maven-javadoc-plugin at all (checked via -X debug
output).
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

/ok to test af54fa7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant