Skip to content

Refactor the code of the background thread used in "fast delete" mode#286

Merged
desruisseaux merged 3 commits into
apache:masterfrom
Geomatys:master
Nov 26, 2025
Merged

Refactor the code of the background thread used in "fast delete" mode#286
desruisseaux merged 3 commits into
apache:masterfrom
Geomatys:master

Conversation

@desruisseaux

Copy link
Copy Markdown
Contributor

Refactor the code of the background thread used in "fast delete" mode:

  • Move the FAST_MODE_* string constants to an enumeration.
  • Move the code for background execution in a separated BakgroundCleaner subclass.
  • Use java.util.concurrent.ExecutorService instead of a thread with our own lifecycle management.
  • Add explanation about why a directory may be moved twice (same algorithm as before, just explained).
  • Reduce the number of directory levels by one (no need for a directory which will always contain exactly one directory).
  • Consolidation of exception handling, including the addition of error reporting at the end.
  • Add tests.

Purpose

Simplify the Cleaner class for the default case (when not using a background thread), have the background code in separated classes, try to make the code slightly safer (Enum, ExecutorService), prepare for the use of more than one thread in the future if we wish to do so (can be done by configuring the ExecutorService).

@desruisseaux desruisseaux added java Pull requests that update Java code maintenance labels Nov 19, 2025
@gnodet gnodet self-requested a review November 20, 2025 05:12
Complete the existing test, which had no `verify.groovy` file.
- Move the `FAST_MODE_*` string constants to an enumeration.
- Move the code for background execution in a separated `BakgroundCleaner` subclass.
- Use `java.util.concurrent.ExecutorService` instead of a thread with our own lifecycle management.
- Add explanation about why a directory may be moved twice (same algorithm as before, just explained).
- Reduce the number of directory levels by one (no need for a directory which will always contain exactly one directory).
- Consolidation of exception handling, including the addition of error reporting at the end.
@desruisseaux

Copy link
Copy Markdown
Contributor Author

This pull request also fixes an issue: the .fastdir temporary directory, created by the "fast mode", was not deleted if it was outside the target directory. The fast-delete integration test had no verify.groovy file for verifying that (this pull request adds that file).

@desruisseaux

Copy link
Copy Markdown
Contributor Author

Another minor issue fixed by this pull request is that the previous code attempted to delete the same directory twice, which caused a log on the second attempt saying the the plugin failed to delete a directory.

Comment thread src/main/java/org/apache/maven/plugins/clean/CleanMojo.java Outdated
* @author Benjamin Bentmann
* @author Martin Desruisseaux
*/
final class BackgroundCleaner extends Cleaner implements Listener, Runnable {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is final really needed here ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not really needed. It is only because I find easier to analyse a code when there are less degrees of freedom (methods behaviour, field values, etc.). Since this class is not public, we do not need to worry about compatibility and can easily remove the final keyword when a subclass is needed.

/**
* Errors that occurred during the deletion.
*/
private IOException errors;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

error ? singular, since it contains only a single exception ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It can contain many exceptions as suppressed exceptions. I will clarify the documentation.

if (errors == null) {
errors = e;
} else {
errors.addSuppressed(e);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if for ease of understanding, it would be better to create a container exception and add the previous one as a suppressed exception. That's how I've seen things so far.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In the current proposal, the first exception is the container for all subsequent exceptions. This is the same behaviour as "try with resource" with two or more resources when exceptions occur in the calls to close(): resources are closed in reverse order, and the first exception is the container for other exceptions (this is true also when the first exception occurred inside the try block).

Admittedly, applying the same pattern to the Maven Clean Plugin is assuming that exceptions after the first one are likely to be indirect consequences of the first exceptions. It is hard to be sure that this assumption is true, but this uncertainty is also true for "try with resources".

I think that the intend is to have stack trace easier to analyse. Leaving apart the topic of checked exceptions, wrapping an exception in another exception is useful when we produce a more informative message. But often, we just put a "Failed to do XYZ" message, and users have to search deeper in the exception chain.

@desruisseaux desruisseaux merged commit 99080f3 into apache:master Nov 26, 2025
8 checks passed
@github-actions github-actions Bot added this to the 4.0.0-beta-3 milestone Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

java Pull requests that update Java code maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants