-
Notifications
You must be signed in to change notification settings - Fork 110
Implement a closeAll
utility to close multiple closeables
#3470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -912,6 +912,32 @@ public static void closeIterator(@Nonnull Iterator<?> iterator) { | |
} | ||
} | ||
|
||
/** | ||
* A utility to close multiple {@link AutoCloseable} objects, preserving all the caught exceptions. | ||
* The method would attempt to close all closeables in order, even if some failed. | ||
* @param closeables the given sequence of {@link AutoCloseable} | ||
* @throws CloseException in case any exception was caught during the process. The first exception will be added | ||
* as a {@code cause}. In case more than one exception was caught, it will be added as Suppressed. | ||
*/ | ||
@SuppressWarnings("PMD.CloseResource") | ||
public static void closeAll(AutoCloseable... closeables) throws CloseException { | ||
ScottDugas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
CloseException accumulatedException = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why create a new exception type to accumulate, rather than setting it to the first exception thrown? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was how I initially tried to implement this but the compiler complained about "close() method can throw InterruptedException" when the |
||
for (AutoCloseable closeable: closeables) { | ||
try { | ||
closeable.close(); | ||
} catch (Exception e) { | ||
if (accumulatedException == null) { | ||
accumulatedException = new CloseException(e); | ||
} else { | ||
accumulatedException.addSuppressed(e); | ||
} | ||
} | ||
} | ||
if (accumulatedException != null) { | ||
throw accumulatedException; | ||
} | ||
} | ||
|
||
/** | ||
* This is supposed to replicate the semantics of {@link java.util.concurrent.CompletionStage#whenComplete(BiConsumer)} | ||
* but to handle the case where the completion handler might itself contain async work. | ||
|
@@ -1081,4 +1107,16 @@ private DeadlineExceededException(long deadlineTimeMillis) { | |
addLogInfo("deadlineTimeMillis", deadlineTimeMillis); | ||
} | ||
} | ||
|
||
/** | ||
* Exception thrown when the {@link #closeAll} method catches an exception. | ||
* This exception will have the cause set to the first exception thrown during {@code closeAll} and any further | ||
* exception thrown will be added as {@Suppressed}. | ||
*/ | ||
@SuppressWarnings("serial") | ||
public static class CloseException extends Exception { | ||
public CloseException(final Throwable cause) { | ||
super(cause); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,14 @@ public static Builder builder(@Nonnull FDBDatabase database, final FDBRecordStor | |
|
||
@Override | ||
public void close() { | ||
throttledIterator.close(); | ||
try { | ||
throttledIterator.close(); | ||
} catch (Exception e) { | ||
if (logger.isWarnEnabled()) { | ||
logger.warn("Failed to close the throttled iterator", e); | ||
} | ||
// Do not rethrow. We are trying to close the runner and the exception should log all errors | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the change here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought this would be a better fit to a usage like:
Where a failure to close would disrupt the flow and cause the loss of already collected results. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems only tangentially related to the purpose of the PR. Also, I'm not sure I agree, I think you would want to do: RepairValidationResults repairResults;
try (RecordRepairValidateRunner repairRunner = builder.buildRepairRunner(false)) {
repairResults = repairRunner.run().join();
// handle results
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reverted to previous behavior. Also, since CloseException is now declared on the signature of the method, I moved the exception to its own top level class. |
||
} | ||
} | ||
|
||
@Nonnull | ||
|
Uh oh!
There was an error while loading. Please reload this page.