Skip to content

Commit a1d4dba

Browse files
authored
Merge pull request #31799 from mkouba/scheduled-executor-service-bean
2 parents 5b7a39b + 4737828 commit a1d4dba

File tree

4 files changed

+90
-6
lines changed

4 files changed

+90
-6
lines changed
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
package io.quarkus.deployment.builditem;
22

3-
import java.util.concurrent.ExecutorService;
3+
import java.util.concurrent.ScheduledExecutorService;
44

55
import io.quarkus.builder.item.SimpleBuildItem;
66

77
/**
88
* The main executor for blocking tasks
99
*/
1010
public final class ExecutorBuildItem extends SimpleBuildItem {
11-
private final ExecutorService executor;
1211

13-
public ExecutorBuildItem(final ExecutorService executor) {
12+
private final ScheduledExecutorService executor;
13+
14+
public ExecutorBuildItem(ScheduledExecutorService executor) {
1415
this.executor = executor;
1516
}
1617

17-
public ExecutorService getExecutorProxy() {
18+
public ScheduledExecutorService getExecutorProxy() {
1819
return executor;
1920
}
2021
}

core/runtime/src/main/java/io/quarkus/runtime/ExecutorRecorder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import java.util.List;
55
import java.util.Optional;
66
import java.util.concurrent.Executor;
7-
import java.util.concurrent.ExecutorService;
7+
import java.util.concurrent.ScheduledExecutorService;
88
import java.util.concurrent.ThreadFactory;
99
import java.util.concurrent.TimeUnit;
1010

@@ -33,7 +33,7 @@ public ExecutorRecorder(ThreadPoolConfig threadPoolConfig) {
3333
this.threadPoolConfig = threadPoolConfig;
3434
}
3535

36-
public ExecutorService setupRunTime(ShutdownContext shutdownContext,
36+
public ScheduledExecutorService setupRunTime(ShutdownContext shutdownContext,
3737
LaunchMode launchMode, ThreadFactory threadFactory, ContextHandler<Object> contextHandler) {
3838
final EnhancedQueueExecutor underlying = createExecutor(threadPoolConfig, threadFactory, contextHandler);
3939
if (launchMode == LaunchMode.DEVELOPMENT) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.quarkus.arc.deployment;
2+
3+
import java.util.concurrent.Executor;
4+
import java.util.concurrent.ExecutorService;
5+
import java.util.concurrent.ScheduledExecutorService;
6+
7+
import io.quarkus.arc.processor.BuiltinScope;
8+
import io.quarkus.deployment.annotations.BuildStep;
9+
import io.quarkus.deployment.builditem.ExecutorBuildItem;
10+
11+
public class ExecutorServiceProcessor {
12+
13+
@BuildStep
14+
SyntheticBeanBuildItem executorServiceBean(ExecutorBuildItem executor) {
15+
return SyntheticBeanBuildItem.configure(ScheduledExecutorService.class)
16+
.types(ExecutorService.class, Executor.class)
17+
.scope(BuiltinScope.APPLICATION.getInfo())
18+
.setRuntimeInit()
19+
.runtimeProxy(executor.getExecutorProxy())
20+
.done();
21+
}
22+
23+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.quarkus.arc.test.executorservice;
2+
3+
import static org.junit.jupiter.api.Assertions.assertNotNull;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.util.concurrent.CountDownLatch;
7+
import java.util.concurrent.Executor;
8+
import java.util.concurrent.ExecutorService;
9+
import java.util.concurrent.ScheduledExecutorService;
10+
import java.util.concurrent.ScheduledFuture;
11+
import java.util.concurrent.TimeUnit;
12+
13+
import jakarta.inject.Inject;
14+
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.RegisterExtension;
17+
18+
import io.quarkus.arc.ClientProxy;
19+
import io.quarkus.test.QuarkusUnitTest;
20+
21+
public class ExecutorServiceBeanTest {
22+
23+
@RegisterExtension
24+
static final QuarkusUnitTest config = new QuarkusUnitTest()
25+
.withApplicationRoot(root -> {
26+
});
27+
28+
@Inject
29+
ExecutorService executorService;
30+
31+
@Inject
32+
Executor executor;
33+
34+
@Inject
35+
ScheduledExecutorService scheduledExecutorService;
36+
37+
@Test
38+
public void testExecutorServiceBean() throws InterruptedException {
39+
// unwrap the proxies first
40+
ExecutorService es = assertNonNullProxy(executorService);
41+
// all injection points should be satisifed by the same application scoped bean
42+
assertTrue(es == assertNonNullProxy(executor));
43+
assertTrue(es == assertNonNullProxy(scheduledExecutorService));
44+
// verify execution
45+
CountDownLatch latch = new CountDownLatch(3);
46+
executorService.submit(() -> latch.countDown());
47+
executor.execute(() -> latch.countDown());
48+
ScheduledFuture<?> sf = scheduledExecutorService.scheduleWithFixedDelay(() -> latch.countDown(), 0, 50,
49+
TimeUnit.MILLISECONDS);
50+
assertTrue(latch.await(3, TimeUnit.SECONDS));
51+
sf.cancel(true);
52+
}
53+
54+
private <T> T assertNonNullProxy(T instance) {
55+
assertNotNull(instance);
56+
assertTrue(instance instanceof ClientProxy);
57+
return ClientProxy.unwrap(instance);
58+
}
59+
60+
}

0 commit comments

Comments
 (0)