Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#367: replaced homebrew async result handling with CompletableFuture
- Loading branch information
Showing
17 changed files
with
10,367 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 0 additions & 38 deletions
38
modules/core-module/src/main/java/org/simplejavamail/api/mailer/AsyncResponse.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 12 additions & 47 deletions
59
...odule/src/main/java/org/simplejavamail/internal/util/concurrent/AsyncOperationHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,41 @@ | ||
package org.simplejavamail.internal.util.concurrent; | ||
|
||
import org.jetbrains.annotations.NotNull; | ||
import org.simplejavamail.api.mailer.AsyncResponse; | ||
import org.slf4j.Logger; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
|
||
import static java.util.concurrent.CompletableFuture.runAsync; | ||
import static java.util.concurrent.Executors.newSingleThreadExecutor; | ||
import static org.simplejavamail.internal.util.Preconditions.assumeTrue; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
/** | ||
* Util that facilitates running a concurrent operation while supporting {@link AsyncResponse}. | ||
* Util that facilitates running a concurrent operation with CompletableFuture support. | ||
*/ | ||
@SuppressWarnings("SameParameterValue") | ||
public class AsyncOperationHelper { | ||
|
||
private static final Logger LOGGER = getLogger(AsyncOperationHelper.class); | ||
|
||
// TODO Lombok | ||
private AsyncOperationHelper() { | ||
} | ||
|
||
/** | ||
* Executes using a single-execution ExecutorService, which shutdown immediately after the thread finishes. | ||
* Executes using a single-execution ExecutorService, which is shutdown immediately after the operation finishes. | ||
* | ||
* @see Executors#newSingleThreadExecutor() | ||
*/ | ||
public static AsyncResponse executeAsync(final @NotNull String processName, | ||
final @NotNull Runnable operation) { | ||
return executeAsync(newSingleThreadExecutor(), processName, operation, true); | ||
public static CompletableFuture<Void> executeAsync(final @NotNull String processName, final @NotNull Runnable operation) { | ||
final ExecutorService executorService = newSingleThreadExecutor(); | ||
return runAsync(new NamedRunnable(processName, operation), executorService) | ||
.thenRun(executorService::shutdown); | ||
} | ||
|
||
/** | ||
* Executes using the given ExecutorService, which is left running after the thread finishes running. | ||
* | ||
* @see Executors#newSingleThreadExecutor() | ||
*/ | ||
public static AsyncResponse executeAsync(final @NotNull ExecutorService executorService, | ||
final @NotNull String processName, | ||
final @NotNull Runnable operation) { | ||
return executeAsync(executorService, processName, operation, false); | ||
} | ||
|
||
private static AsyncResponse executeAsync(final @NotNull ExecutorService executorService, | ||
final @NotNull String processName, | ||
final @NotNull Runnable operation, | ||
final boolean shutDownExecutorService) { | ||
// atomic reference is needed to be able to smuggle the asyncResponse | ||
// into the Runnable which is passed itself to the asyncResponse. | ||
final AtomicReference<AsyncResponseImpl> asyncResponseRef = new AtomicReference<>(); | ||
public static CompletableFuture<Void> executeAsync(final @NotNull ExecutorService executorService, final @NotNull String processName, final @NotNull Runnable operation) { | ||
assumeTrue(!executorService.isShutdown(), "cannot send async email, executor service is already shut down!"); | ||
asyncResponseRef.set(new AsyncResponseImpl(executorService.submit(new NamedRunnable(processName) { | ||
@Override | ||
public void run() { | ||
// by the time the code reaches here, the user would have configured the appropriate handlers | ||
try { | ||
operation.run(); | ||
asyncResponseRef.get().delegateSuccessHandling(); | ||
} catch (Exception e) { | ||
LOGGER.error("Failed to run " + processName, e); | ||
asyncResponseRef.get().delegateExceptionHandling(e); | ||
throw e; // trigger the returned Future's exception handle | ||
} finally { | ||
if (shutDownExecutorService) { | ||
executorService.shutdown(); | ||
} | ||
} | ||
} | ||
|
||
}))); | ||
return asyncResponseRef.get(); | ||
return runAsync(new NamedRunnable(processName, operation), executorService); | ||
} | ||
} | ||
} |
68 changes: 0 additions & 68 deletions
68
...e-module/src/main/java/org/simplejavamail/internal/util/concurrent/AsyncResponseImpl.java
This file was deleted.
Oops, something went wrong.
35 changes: 30 additions & 5 deletions
35
.../core-module/src/main/java/org/simplejavamail/internal/util/concurrent/NamedRunnable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,40 @@ | ||
package org.simplejavamail.internal.util.concurrent; | ||
|
||
public abstract class NamedRunnable implements Runnable { | ||
import org.jetbrains.annotations.NotNull; | ||
import org.slf4j.Logger; | ||
|
||
private final String name; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
protected NamedRunnable(final String name) { | ||
this.name = name; | ||
|
||
/** | ||
* This Runnable is smart in the sense that it can shutdown the | ||
*/ | ||
// TODO LOMBOK | ||
public class NamedRunnable implements Runnable { | ||
|
||
private static final Logger LOGGER = getLogger(NamedRunnable.class); | ||
|
||
@NotNull private final String processName; | ||
@NotNull private final Runnable operation; | ||
|
||
protected NamedRunnable(@NotNull String processName, @NotNull Runnable operation) { | ||
this.processName = processName; | ||
this.operation = operation; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
// by the time the code reaches here, the user would have configured the appropriate handlers | ||
try { | ||
operation.run(); | ||
} catch (Exception e) { | ||
LOGGER.error("Failed to run " + processName, e); | ||
throw e; | ||
} | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return name; | ||
return processName; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.