Skip to content

Conversation

shs96c
Copy link
Collaborator

@shs96c shs96c commented Sep 17, 2025

This can significantly improve the time it takes to perform resolutions.

@shs96c shs96c requested review from jin and cheister as code owners September 17, 2025 19:05
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @shs96c, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a key optimization for Gradle resolution performance within rules_jvm_external. It refines the mechanism for utilizing a shared Gradle user cache when RJE_UNSAFE_CACHE is active. The core change involves replacing the direct setting of the gradle.user.home system property with a more robust symbolic linking approach, connecting the temporary project's cache directory to the user's global Gradle cache. This aims to mitigate timing-related issues and ensures a more reliable shared cache experience, with built-in error handling and informative logging for fallback scenarios.

Highlights

  • Performance Improvement: The primary goal of this change is to significantly improve Gradle resolution times by leveraging a shared user cache when RJE_UNSAFE_CACHE is enabled.
  • Cache Handling Strategy: Instead of directly setting the gradle.user.home system property, the approach now involves creating a symbolic link from the temporary project's .gradle/caches directory to the user's global .gradle/caches directory. This avoids potential timing issues.
  • Robust Symlinking with Fallback: The implementation includes checks for the existence of the user's cache directory and robust error handling for symbolic link creation. If symlinking fails or the user cache is not found, the system gracefully falls back to using an isolated cache.
  • Verbose Logging: Added verbose logging to provide clear feedback on whether the unsafe shared cache is being utilized via symlinking or if the system has reverted to an isolated cache.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request changes the unsafe caching mechanism for Gradle resolutions to use symbolic links to the user's cache directory instead of setting gradle.user.home. This is a solid approach to improve performance while avoiding potential timing issues. The implementation correctly falls back to an isolated cache if creating the symlink fails. I have one suggestion to make the check for the user's cache directory more robust.

Comment on lines 456 to 483
if (Files.exists(userCaches)) {
try {
Path cacheSymlink = gradleCacheDir.resolve("caches");
Files.createSymbolicLink(cacheSymlink, userCaches);
if (isVerbose()) {
eventListener.onEvent(
new LogEvent(
"gradle",
"Using unsafe shared cache",
"Symlinked " + userCaches + " -> " + cacheSymlink));
}
} catch (IOException e) {
// If symlinking fails, fall back to isolated cache
if (isVerbose()) {
eventListener.onEvent(
new LogEvent(
"gradle",
"Failed to create cache symlink, using isolated cache",
e.getMessage()));
}
}
} else if (isVerbose()) {
eventListener.onEvent(
new LogEvent(
"gradle",
"User gradle caches directory not found, using isolated cache",
"Expected: " + userCaches));
}

Choose a reason for hiding this comment

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

medium

Using Files.exists() here could lead to issues if userCaches points to a file instead of a directory. Files.exists() returns true for files, and createSymbolicLink would succeed, but Gradle would later fail when it expects a directory for its cache.

Using Files.isDirectory() is more robust as it ensures that we only attempt to symlink if the target is a directory. I've also updated the logging in the else branch to be more descriptive about why the symlink was not created.

        if (Files.isDirectory(userCaches)) {
          try {
            Path cacheSymlink = gradleCacheDir.resolve("caches");
            Files.createSymbolicLink(cacheSymlink, userCaches);
            if (isVerbose()) {
              eventListener.onEvent(
                  new LogEvent(
                      "gradle",
                      "Using unsafe shared cache",
                      "Symlinked " + userCaches + " -> " + cacheSymlink));
            }
          } catch (IOException e) {
            // If symlinking fails, fall back to isolated cache
            if (isVerbose()) {
              eventListener.onEvent(
                  new LogEvent(
                      "gradle",
                      "Failed to create cache symlink, using isolated cache",
                      e.getMessage()));
            }
          }
        } else if (isVerbose()) {
          String reason = Files.exists(userCaches) ? "is not a directory" : "not found";
          eventListener.onEvent(
              new LogEvent(
                  "gradle",
                  "User gradle caches directory " + reason + ", using isolated cache",
                  "Expected: " + userCaches));
        }

@shs96c shs96c force-pushed the gradle-resolver-symlink-cache branch from d345cdf to 23c6061 Compare October 6, 2025 16:12
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