Skip to content

Conversation

@FinlayRJW
Copy link
Contributor

@FinlayRJW FinlayRJW commented Dec 1, 2025

Before this PR

  • palantir-java-format ran in-process for Spotless integration
  • Formatter crashes could take down the entire Gradle daemon
  • Error messages were unclear when formatting failed
  • No process isolation between formatting and the main build

After this PR

  • Spotless uses Gradle's Worker API with process isolation
  • JVM exports are automatically configured in worker daemons - no user configuration needed
  • Formatter crashes only affect isolated worker daemons, not the main build
  • Better error messages when formatting fails

==COMMIT_MSG==
Use Worker API for process isolation in Spotless and FormatDiff

Migrates Spotless integration to use Gradle's Worker
API with process isolation. Provides better error messages and prevents
formatter crashes from affecting the main build daemon.
==COMMIT_MSG==

Possible downsides?

@changelog-app
Copy link

changelog-app bot commented Dec 1, 2025

Generate changelog in changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

Use Worker API for process isolation in Spotless and FormatDiff

Migrates Spotless integration to use Gradle's Worker
API with process isolation. Provides better error messages and prevents
formatter crashes from affecting the main build daemon.

Check the box to generate changelog(s)

  • Generate changelog entry


private String formatWithWorker(String input, Iterable<File> jars) throws IOException {
// Create temp files for input/output communication with worker
File inputFile =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the best way I could come-up with to get the formatted string in and out

parameters.getFormatterClasspath().from(jars);
});

workQueue.await();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

need to await to ensure formatting is done

@FinlayRJW FinlayRJW changed the title Use Worker API for process isolation in Spotless and FormatDiff Use Worker API for process isolation in Spotless Dec 1, 2025
@changelog-app
Copy link

changelog-app bot commented Dec 1, 2025

Successfully generated changelog entry!

Need to regenerate?

Simply interact with the changelog bot comment again to regenerate these entries.


📋Changelog Preview

💡 Improvements

  • Use Worker API for process isolation in Spotless and FormatDiff

    Migrates Spotless integration to use Gradle's Worker
    API with process isolation. Provides better error messages and prevents
    formatter crashes from affecting the main build daemon. (#1492)

@FinlayRJW FinlayRJW requested a review from CRogers December 1, 2025 17:33
try {
Files.writeString(inputFile.toPath(), input);

WorkQueue workQueue = workerExecutor.processIsolation(workerSpec -> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm failure rate has increased to about 30% I wonder if this is just adding loads of overhead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As we are creating a temp io file and a new worker for every single file

private static final Logger logger = Logging.getLogger(FormatJavaWorkAction.class);

private static final Supplier<FormatterService> formatterService = Suppliers.memoize(() -> {
logger.info("Loading FormatterService in worker daemon");
Copy link
Contributor

Choose a reason for hiding this comment

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

Running this locally, does it log this per file or just once per gradle invocation? Not sure is gradle is doing something funky with classloaders even in process isolation that means this may be new each time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

once per gradle invocation - or at least per spotless invocation:

> Task :foo-api:spotlessJava
Formatting file #1 in worker - classIdentity=269645944, file=palantir-java-format-input-1956597832421626908.java
Loading FormatterService in worker daemon - classLoader=VisitableURLClassLoader(worker-loader), classIdentity=269645944

> Task :foo:spotlessJava
Formatting file #1 in worker - classIdentity=687141933, file=palantir-java-format-input-12790676627999507747.java
Loading FormatterService in worker daemon - classLoader=VisitableURLClassLoader(worker-loader), classIdentity=687141933
Formatting file #2 in worker - classIdentity=269645944, file=palantir-java-format-input-1807148048456068675.java
Formatting file #2 in worker - classIdentity=687141933, file=palantir-java-format-input-12981619963290984761.java
Formatting file #3 in worker - classIdentity=269645944, file=palantir-java-format-input-13174205067034597682.java
Formatting file #3 in worker - classIdentity=687141933, file=palantir-java-format-input-7978830245738795631.java

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.

3 participants