Skip to content

Commit 5c7bfb0

Browse files
authored
Merge pull request #608 from optimaster/server-worker-executor
Server worker executor
2 parents 5b38191 + d8bfdc0 commit 5c7bfb0

11 files changed

Lines changed: 141 additions & 0 deletions

File tree

jooby-jetty/src/main/java/org/jooby/internal/jetty/JettyServer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.lang.reflect.Method;
2323
import java.util.Arrays;
2424
import java.util.Map;
25+
import java.util.Optional;
26+
import java.util.concurrent.Executor;
2527
import java.util.concurrent.TimeUnit;
2628
import java.util.function.Function;
2729
import java.util.stream.Collectors;
@@ -194,6 +196,12 @@ public void stop() throws Exception {
194196
server.stop();
195197
}
196198

199+
@Override
200+
public Optional<Executor> executor()
201+
{
202+
return Optional.ofNullable(server.getThreadPool());
203+
}
204+
197205
private void tryOption(final Object source, final Config config, final Method option) {
198206
Try.run(() -> {
199207
String optionName = option.getName().replace("set", "");

jooby-jetty/src/test/java/org/jooby/internal/jetty/JettyServerTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package org.jooby.internal.jetty;
22

3+
import static org.easymock.EasyMock.expect;
34
import static org.easymock.EasyMock.expectLastCall;
45
import static org.easymock.EasyMock.isA;
6+
import static org.junit.Assert.assertNotNull;
7+
import static org.junit.Assert.assertTrue;
58

69
import java.util.Map;
710

@@ -109,6 +112,8 @@ public class JettyServerTest {
109112
server.stop();
110113

111114
unit.registerMock(Server.class, server);
115+
116+
expect(server.getThreadPool()).andReturn(unit.get(QueuedThreadPool.class)).anyTimes();
112117
};
113118

114119
private MockUnit.Block httpConf = unit -> {
@@ -194,7 +199,9 @@ public void startStopServer() throws Exception {
194199
JettyServer server = new JettyServer(unit.get(HttpHandler.class), config,
195200
unit.get(Provider.class));
196201

202+
assertNotNull(server.executor());
197203
server.start();
204+
assertTrue(server.executor().isPresent());
198205
server.join();
199206
server.stop();
200207
});

jooby-netty/src/main/java/org/jooby/internal/netty/NettyServer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.lang.reflect.ParameterizedType;
2727
import java.util.Map;
2828
import java.util.Map.Entry;
29+
import java.util.Optional;
30+
import java.util.concurrent.Executor;
2931
import java.util.concurrent.ThreadFactory;
3032
import java.util.function.BiConsumer;
3133

@@ -152,6 +154,12 @@ public void join() throws InterruptedException {
152154
ch.closeFuture().sync();
153155
}
154156

157+
@Override
158+
public Optional<Executor> executor()
159+
{
160+
return Optional.ofNullable(executor);
161+
}
162+
155163
@SuppressWarnings({"rawtypes", "unchecked" })
156164
private void configure(final Config config, final String path,
157165
final BiConsumer<ChannelOption<Object>, Object> setter) {

jooby-netty/src/test/java/org/jooby/internal/netty/NettyServerTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.jooby.internal.netty;
22

3+
import static org.junit.Assert.assertNotNull;
4+
import static org.junit.Assert.assertTrue;
5+
36
import static org.easymock.EasyMock.expect;
47
import static org.easymock.EasyMock.isA;
58

@@ -117,7 +120,9 @@ public void defaultServer() throws Exception {
117120
.run(unit -> {
118121
NettyServer server = new NettyServer(unit.get(HttpHandler.class), config);
119122
try {
123+
assertNotNull(server.executor());
120124
server.start();
125+
assertTrue(server.executor().isPresent());
121126
server.join();
122127
} finally {
123128
server.stop();

jooby-servlet/src/main/java/org/jooby/servlet/ServletContainer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
import org.jooby.spi.Server;
2222

23+
import java.util.Optional;
24+
import java.util.concurrent.Executor;
25+
2326
/**
2427
* NOOP server for servlets.
2528
*
@@ -44,4 +47,9 @@ public void stop() throws Exception {
4447
public void join() throws InterruptedException {
4548
}
4649

50+
@Override
51+
public Optional<Executor> executor() {
52+
return Optional.empty();
53+
}
54+
4755
}

jooby-undertow/src/main/java/org/jooby/internal/undertow/UndertowServer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import java.lang.reflect.Field;
2222
import java.util.Map;
23+
import java.util.Optional;
24+
import java.util.concurrent.Executor;
2325
import java.util.concurrent.TimeUnit;
2426
import java.util.function.BiConsumer;
2527
import java.util.function.Consumer;
@@ -206,4 +208,10 @@ public void stop() throws Exception {
206208
server.stop();
207209
}
208210

211+
@Override
212+
public Optional<Executor> executor()
213+
{
214+
return Optional.ofNullable(server.getWorker());
215+
}
216+
209217
}

jooby-undertow/src/test/java/org/jooby/internal/undertow/UndertowServerTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.jooby.internal.undertow;
22

3+
import static org.junit.Assert.assertNotNull;
4+
import static org.junit.Assert.assertTrue;
5+
36
import javax.inject.Provider;
47

58
import org.jooby.spi.HttpHandler;
@@ -37,7 +40,9 @@ public void server() throws Exception {
3740
UndertowServer server = new UndertowServer(unit.get(HttpHandler.class), config,
3841
unit.get(Provider.class));
3942
try {
43+
assertNotNull(server.executor());
4044
server.start();
45+
assertTrue(server.executor().isPresent());
4146
server.join();// NOOP
4247
} finally {
4348
server.stop();

jooby/src/main/java/org/jooby/Jooby.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
import org.jooby.internal.ParameterNameProvider;
109109
import org.jooby.internal.RequestScope;
110110
import org.jooby.internal.RouteMetadata;
111+
import org.jooby.internal.ServerExecutorProvider;
111112
import org.jooby.internal.ServerLookup;
112113
import org.jooby.internal.ServerSessionManager;
113114
import org.jooby.internal.SessionManager;
@@ -2415,6 +2416,24 @@ public Jooby executor(final String name) {
24152416
return this;
24162417
}
24172418

2419+
/**
2420+
* Set a named executor to use from {@link Deferred Deferred API}. Useful for override the
2421+
* default/global executor.
2422+
*
2423+
* Default executor runs each task in the thread that invokes {@link Executor#execute execute},
2424+
* that's a Jooby worker thread. A worker thread in Jooby can block.
2425+
*
2426+
* @param name Name of the executor.
2427+
* @param provider Provider for the executor.
2428+
* @return This jooby instance.
2429+
*/
2430+
private Jooby executor(final String name, final Class<? extends Provider<Executor>> provider) {
2431+
this.executors.add(binder -> {
2432+
binder.bind(Key.get(Executor.class, Names.named(name))).toProvider(provider).in(Singleton.class);
2433+
});
2434+
return this;
2435+
}
2436+
24182437
/**
24192438
* If the application fails to start all the services are shutdown. Also, the exception is logged
24202439
* and usually the application is going to exit.
@@ -2565,6 +2584,7 @@ private Injector bootstrap(final Config args,
25652584
executor(MoreExecutors.directExecutor());
25662585
}
25672586
executor("direct", MoreExecutors.directExecutor());
2587+
executor("server", ServerExecutorProvider.class);
25682588

25692589
/** Some basic xss functions. */
25702590
xss(finalEnv);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.jooby.internal;
20+
21+
import com.google.common.util.concurrent.MoreExecutors;
22+
import com.google.inject.Inject;
23+
import com.google.inject.Provider;
24+
import org.jooby.spi.Server;
25+
26+
import java.util.concurrent.Executor;
27+
28+
import static java.util.Objects.requireNonNull;
29+
30+
public class ServerExecutorProvider implements Provider<Executor>
31+
{
32+
33+
private Executor executor;
34+
35+
@Inject
36+
public ServerExecutorProvider(final ServerHolder serverHolder) {
37+
requireNonNull(serverHolder, "Server holder is required.");
38+
39+
executor = (serverHolder.server != null) ?
40+
serverHolder.server.executor().orElse(MoreExecutors.directExecutor()) :
41+
MoreExecutors.directExecutor();
42+
}
43+
44+
@Override
45+
public Executor get() {
46+
return executor;
47+
}
48+
49+
static class ServerHolder {
50+
51+
@Inject(optional = true) Server server = null;
52+
53+
}
54+
55+
}

jooby/src/main/java/org/jooby/spi/Server.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package org.jooby.spi;
2020

21+
import java.util.Optional;
22+
import java.util.concurrent.Executor;
2123

2224
/**
2325
* A HTTP web server.
@@ -48,4 +50,11 @@ public interface Server {
4850
*/
4951
void join() throws InterruptedException;
5052

53+
/**
54+
* Obtain the executor for worker threads.
55+
*
56+
* @return The executor for worker threads.
57+
*/
58+
Optional<Executor> executor();
59+
5160
}

0 commit comments

Comments
 (0)