Skip to content

Commit

Permalink
Make config disabled tests use AsyncTaskManager (#633)
Browse files Browse the repository at this point in the history
* Make config disabled tests use AsyncTaskManager

Previously these tests were using a fixed thread pool executor which
will create unmanaged threads on a Jakarta EE server.

* Release doc for removal of TCK unmanaged threads
  • Loading branch information
Azquelt committed Jun 27, 2024
1 parent 3543ebc commit 48c90e7
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 299 deletions.
3 changes: 3 additions & 0 deletions spec/src/main/asciidoc/release_notes.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ No.
=== Specification changes
- Work with MicroProfile Telemetry Metrics (link:https://github.com/eclipse/microprofile-fault-tolerance/issues/622[#622])

=== Other Changes
- Removed use of unmanaged threads in TCK (link:https://github.com/eclipse/microprofile-fault-tolerance/issues/634[#634])

[[release_notes_40]]
== Release Notes for MicroProfile Fault Tolerance 4.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
package org.eclipse.microprofile.fault.tolerance.tck.disableEnv;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.eclipse.microprofile.fault.tolerance.tck.util.ConcurrentExecutionTracker;
import org.eclipse.microprofile.fault.tolerance.tck.util.Barrier;
import org.eclipse.microprofile.fault.tolerance.tck.util.TCKConfig;
import org.eclipse.microprofile.fault.tolerance.tck.util.TestException;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
Expand All @@ -34,7 +33,6 @@
import org.eclipse.microprofile.faulttolerance.Timeout;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

/**
* A client to determine the impact of disabling annotations via config
Expand All @@ -50,9 +48,6 @@ public class DisableAnnotationClient {
private int failAndRetryOnceCounter = 0;
private int failRetryOnceThenFallbackCounter = 0;

@Inject
private ConcurrentExecutionTracker tracker;

/**
* Always throws {@link TestException}, should increment counter by two if Retry is enabled, or one if it is not
*/
Expand Down Expand Up @@ -125,35 +120,16 @@ public void failWithTimeout() {
}

/**
* Blocks waiting for {@code waitingFuture} to complete
* <p>
* If passed an already completed {@link Future}, this method will return immediately.
* Blocks waiting for {@code barrier} to complete
* <p>
* Should permit two simultaneous calls if bulkhead enabled, or more if bulkhead disabled.
*
* @param waitingFuture
* the future to wait for
* @param barrier
* the barrier to wait for
*/
@Bulkhead(2)
public void waitWithBulkhead(Future<?> waitingFuture) {
try {
tracker.executionStarted();
waitingFuture.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
} finally {
tracker.executionEnded();
}
}

/**
* Wait for {@code count} executions of {@link #waitWithBulkhead(Future)} to be in progress.
*
* @param count
* execution count
*/
public void waitForBulkheadExecutions(int count) {
tracker.waitForRunningExecutions(count);
public void waitWithBulkhead(Barrier barrier) {
barrier.await();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@

import static org.eclipse.microprofile.fault.tolerance.tck.util.TCKConfig.getConfig;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.eclipse.microprofile.fault.tolerance.tck.config.ConfigAnnotationAsset;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncCaller;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager.BarrierTask;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.fault.tolerance.tck.util.TestException;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
Expand Down Expand Up @@ -85,7 +85,8 @@ public static WebArchive deploy() {
.disable(DisableAnnotationClient.class, "failWithTimeout", Timeout.class)
.disable(DisableAnnotationClient.class, "asyncWaitThenReturn", Asynchronous.class)
.disable(DisableAnnotationClient.class, "failRetryOnceThenFallback", Fallback.class)
.disable(DisableAnnotationClient.class, "waitWithBulkhead", Bulkhead.class);
.disable(DisableAnnotationClient.class, "waitWithBulkhead", Bulkhead.class)
.enable(AsyncCaller.class, Asynchronous.class); // Needed by AsyncTaskManager

final ConfigAnnotationAsset mpAnnotationConfig = new ConfigAnnotationAsset()
.setValue(DisableAnnotationClient.class, "failWithTimeout", Timeout.class,
Expand Down Expand Up @@ -173,34 +174,22 @@ public void testAsync() throws InterruptedException, ExecutionException {

/**
* Test whether Bulkhead is enabled on {@code waitWithBulkhead()}
*
* @throws InterruptedException
* interrupted
* @throws ExecutionException
* task was aborted
*/
@Test
public void testBulkhead() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
public void testBulkhead() {

// Start two executions at once
CompletableFuture<Void> waitingFuture = new CompletableFuture<>();
Future<?> result1 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
Future<?> result2 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));

try {
disableClient.waitForBulkheadExecutions(2);
try (AsyncTaskManager taskManager = new AsyncTaskManager()) {
// Start two executions at once
BarrierTask<?> task1 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
BarrierTask<?> task2 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task1.assertAwaits();
task2.assertAwaits();

// Try to start a third execution. This would throw a BulkheadException if Bulkhead is enabled.
// Bulkhead is disabled on the method so no exception expected
disableClient.waitWithBulkhead(CompletableFuture.completedFuture(null));
} finally {
// Clean up executor and first two executions
executor.shutdown();

waitingFuture.complete(null);
result1.get();
result2.get();
BarrierTask<?> task3 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task3.openBarrier();
task3.assertSuccess();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
*******************************************************************************/
package org.eclipse.microprofile.fault.tolerance.tck.disableEnv;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncCaller;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager.BarrierTask;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.fault.tolerance.tck.util.TestException;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
Expand Down Expand Up @@ -74,7 +74,8 @@ public static WebArchive deploy() {
.enable(DisableAnnotationClient.class, Timeout.class)
.enable(DisableAnnotationClient.class, Asynchronous.class)
.enable(DisableAnnotationClient.class, Fallback.class)
.enable(DisableAnnotationClient.class, Bulkhead.class);
.enable(DisableAnnotationClient.class, Bulkhead.class)
.enable(AsyncCaller.class, Asynchronous.class); // Needed by AsyncTaskManager

JavaArchive testJar = ShrinkWrap
.create(JavaArchive.class, "ftDisableGlobalEnableClass.jar")
Expand Down Expand Up @@ -155,35 +156,22 @@ public void testAsync() throws InterruptedException, ExecutionException {

/**
* Test whether Bulkhead is enabled on {@code waitWithBulkhead()}
*
* @throws InterruptedException
* interrupted
* @throws ExecutionException
* task was aborted
*/
@Test
public void testBulkhead() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
public void testBulkhead() {

// Start two executions at once
CompletableFuture<Void> waitingFuture = new CompletableFuture<>();
Future<?> result1 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
Future<?> result2 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));

try {
disableClient.waitForBulkheadExecutions(2);
try (AsyncTaskManager taskManager = new AsyncTaskManager()) {
// Start two executions at once
BarrierTask<?> task1 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
BarrierTask<?> task2 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task1.assertAwaits();
task2.assertAwaits();

// Try to start a third execution. This would throw a BulkheadException if Bulkhead is enabled.
// Bulkhead is enabled on the class, so expect exception
Assert.assertThrows(BulkheadException.class,
() -> disableClient.waitWithBulkhead(CompletableFuture.completedFuture(null)));
} finally {
// Clean up executor and first two executions
executor.shutdown();

waitingFuture.complete(null);
result1.get();
result2.get();
BarrierTask<?> task3 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task3.openBarrier();
task3.assertThrows(BulkheadException.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
*******************************************************************************/
package org.eclipse.microprofile.fault.tolerance.tck.disableEnv;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncCaller;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager.BarrierTask;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.fault.tolerance.tck.util.TestException;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
Expand Down Expand Up @@ -74,7 +74,8 @@ public static WebArchive deploy() {
.enable(DisableAnnotationClient.class, "failWithTimeout", Timeout.class)
.enable(DisableAnnotationClient.class, "asyncWaitThenReturn", Asynchronous.class)
.enable(DisableAnnotationClient.class, "failRetryOnceThenFallback", Fallback.class)
.enable(DisableAnnotationClient.class, "waitWithBulkhead", Bulkhead.class);
.enable(DisableAnnotationClient.class, "waitWithBulkhead", Bulkhead.class)
.enable(AsyncCaller.class, Asynchronous.class); // Needed by AsyncTaskManager

JavaArchive testJar = ShrinkWrap
.create(JavaArchive.class, "ftDisableGloballyEnableMethod.jar")
Expand Down Expand Up @@ -157,36 +158,22 @@ public void testAsync() throws InterruptedException, ExecutionException {

/**
* Test whether Bulkhead is enabled on {@code waitWithBulkhead()}
*
* @throws InterruptedException
* interrupted
* @throws ExecutionException
* task was aborted
*
*/
@Test
public void testBulkhead() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);

// Start two executions at once
CompletableFuture<Void> waitingFuture = new CompletableFuture<>();
Future<?> result1 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
Future<?> result2 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
public void testBulkhead() {

try {
disableClient.waitForBulkheadExecutions(2);
try (AsyncTaskManager taskManager = new AsyncTaskManager()) {
// Start two executions at once
BarrierTask<?> task1 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
BarrierTask<?> task2 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task1.assertAwaits();
task2.assertAwaits();

// Try to start a third execution. This would throw a BulkheadException if Bulkhead is enabled.
// Bulkhead is enabled on the method, so expect exception
Assert.assertThrows(BulkheadException.class,
() -> disableClient.waitWithBulkhead(CompletableFuture.completedFuture(null)));
} finally {
// Clean up executor and first two executions
executor.shutdown();

waitingFuture.complete(null);
result1.get();
result2.get();
BarrierTask<?> task3 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task3.openBarrier();
task3.assertThrows(BulkheadException.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
*******************************************************************************/
package org.eclipse.microprofile.fault.tolerance.tck.disableEnv;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncCaller;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager;
import org.eclipse.microprofile.fault.tolerance.tck.util.AsyncTaskManager.BarrierTask;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.fault.tolerance.tck.util.TestException;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
Expand Down Expand Up @@ -69,7 +69,8 @@ public static WebArchive deploy() {
.disable(Timeout.class)
.disable(Asynchronous.class)
.disable(Fallback.class)
.disable(Bulkhead.class);
.disable(Bulkhead.class)
.enable(AsyncCaller.class, Asynchronous.class); // Needed by AsyncTaskManager;

JavaArchive testJar = ShrinkWrap
.create(JavaArchive.class, "ftDisableGlobally.jar")
Expand Down Expand Up @@ -153,34 +154,22 @@ public void testAsync() throws InterruptedException, ExecutionException {

/**
* Test whether Bulkhead is enabled on {@code waitWithBulkhead()}
*
* @throws InterruptedException
* interrupted
* @throws ExecutionException
* task was aborted
*/
@Test
public void testBulkhead() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
public void testBulkhead() {

// Start two executions at once
CompletableFuture<Void> waitingFuture = new CompletableFuture<>();
Future<?> result1 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
Future<?> result2 = executor.submit(() -> disableClient.waitWithBulkhead(waitingFuture));
try (AsyncTaskManager taskManager = new AsyncTaskManager()) {
// Start two executions at once
BarrierTask<?> task1 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
BarrierTask<?> task2 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task1.assertAwaits();
task2.assertAwaits();

try {
disableClient.waitForBulkheadExecutions(2);

// Try to start a third execution. This should throw a BulkheadException if Bulkhead is enabled.
// Try to start a third execution. This would throw a BulkheadException if Bulkhead is enabled.
// Bulkhead is globally disabled so expect no exception
disableClient.waitWithBulkhead(CompletableFuture.completedFuture(null));
} finally {
// Clean up executor and first two executions
executor.shutdown();

waitingFuture.complete(null);
result1.get();
result2.get();
BarrierTask<?> task3 = taskManager.runBarrierTask(disableClient::waitWithBulkhead);
task3.openBarrier();
task3.assertSuccess();
}
}
}
Loading

0 comments on commit 48c90e7

Please sign in to comment.