Skip to content

Commit bddaf2c

Browse files
committed
Document and rename ExecutionMode
1 parent aba7bcd commit bddaf2c

17 files changed

Lines changed: 185 additions & 93 deletions

File tree

future/src/main/java/io/jooby/App.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class App implements Router {
2323
private Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"), appname(getClass()))
2424
.toAbsolutePath();
2525

26-
private Mode mode = Mode.WORKER;
26+
private ExecutionMode mode = ExecutionMode.DEFAULT;
2727

2828
public App() {
2929
router = new RouterImpl(new RouteAnalyzer(getClass().getClassLoader(), false));
@@ -149,11 +149,11 @@ public App tmpdir(@Nonnull Path tmpdir) {
149149
return this;
150150
}
151151

152-
public Mode mode() {
152+
public ExecutionMode mode() {
153153
return mode;
154154
}
155155

156-
public App mode(Mode mode) {
156+
public App mode(ExecutionMode mode) {
157157
this.mode = mode;
158158
return this;
159159
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package io.jooby;
2+
3+
/**
4+
* Execution mode.
5+
*
6+
* @author edgar
7+
*/
8+
public enum ExecutionMode {
9+
/**
10+
* Execute route handler in the event loop thread (non-blocking). Handler must never block.
11+
*
12+
* Examples:
13+
* <pre>{@code
14+
* {
15+
* mode(EVENT_LOOP);
16+
*
17+
* get("/non-blocking", ctx -> "I'm running on event-loop thread (no blocking allowed)");
18+
*
19+
* // Dispatch to worker thread, blocking routes
20+
* dispatch(() -> {
21+
*
22+
* get("/blocking", ctx -> {
23+
* // remote call: service, database, etc..
24+
* return "Safe to block";
25+
* });
26+
* });
27+
* }
28+
* }</pre>
29+
*/
30+
EVENT_LOOP,
31+
32+
/**
33+
* Execute handler in a worker/io thread (blocking). Handler is allowed to block.
34+
*
35+
* Examples:
36+
* <pre>{@code
37+
* {
38+
*
39+
* mode(WORKER);
40+
*
41+
* get("/worker", cxtx -> {
42+
* // remote call: another service, database, etc..
43+
* return "Safe to block";
44+
* });
45+
* }
46+
*
47+
* }</pre>
48+
*/
49+
WORKER,
50+
51+
/**
52+
* Default execution mode.
53+
*
54+
* Automatically choose between {@link ExecutionMode#EVENT_LOOP} and {@link ExecutionMode#WORKER}.
55+
*
56+
* If route handler returns a `reactive` type, then Jooby run the route handler in the event-loop
57+
* thread. Otherwise, run the handler in the worker thread.
58+
*
59+
* A reactive type is one of:
60+
*
61+
* - {@link java.util.concurrent.CompletableFuture}.
62+
* - {@link java.util.concurrent.Flow.Publisher}
63+
* - A reactive stream Publisher
64+
* - Rx types: Observable, Flowable, Single, Maybe, etc..
65+
* - Reactor types: Flux and Mono.
66+
*
67+
* Examples:
68+
* <pre>{@code
69+
* {
70+
*
71+
* get("/non-blocking", ctx -> {
72+
* return CompletableFuture.supplyAsync(() -> {
73+
* return "I'm non-blocking";
74+
* });
75+
* });
76+
*
77+
* get("/blocking", ctx -> {
78+
* return "I'm blocking";
79+
* });
80+
* }
81+
* }</pre>
82+
*/
83+
DEFAULT
84+
}

future/src/main/java/io/jooby/Mode.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

future/src/main/java/io/jooby/internal/Pipeline.java

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package io.jooby.internal;
22

3-
import io.jooby.Mode;
3+
import io.jooby.ExecutionMode;
44
import io.jooby.Reified;
55
import io.jooby.Route.Handler;
66
import io.jooby.internal.handler.CompletionStageHandler;
77
import io.jooby.internal.handler.DefaultHandler;
88
import io.jooby.internal.handler.DetachHandler;
9-
import io.jooby.internal.handler.ExecutorHandler;
9+
import io.jooby.internal.handler.WorkerExecHandler;
1010
import io.jooby.internal.handler.FlowPublisherHandler;
1111
import io.jooby.internal.handler.FluxHandler;
1212
import io.jooby.internal.handler.MaybeHandler;
@@ -24,11 +24,11 @@
2424

2525
public class Pipeline {
2626

27-
public static Handler compute(ClassLoader loader, RouteImpl route, Mode mode) {
27+
public static Handler compute(ClassLoader loader, RouteImpl route, ExecutionMode mode) {
2828
return provider(loader, Reified.rawType(route.returnType())).apply(mode, route);
2929
}
3030

31-
private static BiFunction<Mode, RouteImpl, Handler> provider(ClassLoader loader, Class type) {
31+
private static BiFunction<ExecutionMode, RouteImpl, Handler> provider(ClassLoader loader, Class type) {
3232
if (CompletionStage.class.isAssignableFrom(type)) {
3333
return Pipeline::completableFuture;
3434
}
@@ -86,48 +86,58 @@ private static BiFunction<Mode, RouteImpl, Handler> provider(ClassLoader loader,
8686
if (Flow.Publisher.class.isAssignableFrom(type)) {
8787
return Pipeline::flowPublisher;
8888
}
89-
return (mode, route) -> next(mode, route.executor(), new DefaultHandler(route.pipeline()));
89+
return (mode, route) -> next(mode, route.executor(), new DefaultHandler(route.pipeline()),
90+
true);
9091
}
9192

92-
private static Handler completableFuture(Mode mode, RouteImpl next) {
93+
private static Handler completableFuture(ExecutionMode mode, RouteImpl next) {
9394
return next(mode, next.executor(),
94-
new DetachHandler(new CompletionStageHandler(next.pipeline())));
95+
new DetachHandler(new CompletionStageHandler(next.pipeline())), false);
9596
}
9697

97-
private static Handler publisher(Mode mode, RouteImpl next) {
98-
return next(mode, next.executor(), new DetachHandler(new PublisherHandler(next.pipeline())));
98+
private static Handler publisher(ExecutionMode mode, RouteImpl next) {
99+
return next(mode, next.executor(), new DetachHandler(new PublisherHandler(next.pipeline())),
100+
false);
99101
}
100102

101-
private static Handler observable(Mode mode, RouteImpl next) {
102-
return next(mode, next.executor(), new DetachHandler(new ObservableHandler(next.pipeline())));
103+
private static Handler observable(ExecutionMode mode, RouteImpl next) {
104+
return next(mode, next.executor(), new DetachHandler(new ObservableHandler(next.pipeline())),
105+
false);
103106
}
104107

105-
private static Handler flux(Mode mode, RouteImpl next) {
106-
return next(mode, next.executor(), new DetachHandler(new FluxHandler(next.pipeline())));
108+
private static Handler flux(ExecutionMode mode, RouteImpl next) {
109+
return next(mode, next.executor(), new DetachHandler(new FluxHandler(next.pipeline())), false);
107110
}
108111

109-
private static Handler mono(Mode mode, RouteImpl next) {
110-
return next(mode, next.executor(), new DetachHandler(new MonoHandler(next.pipeline())));
112+
private static Handler mono(ExecutionMode mode, RouteImpl next) {
113+
return next(mode, next.executor(), new DetachHandler(new MonoHandler(next.pipeline())), false);
111114
}
112115

113-
private static Handler flowPublisher(Mode mode, RouteImpl next) {
116+
private static Handler flowPublisher(ExecutionMode mode, RouteImpl next) {
114117
return next(mode, next.executor(),
115-
new DetachHandler(new FlowPublisherHandler(next.pipeline())));
118+
new DetachHandler(new FlowPublisherHandler(next.pipeline())), false);
116119
}
117120

118-
private static Handler single(Mode mode, RouteImpl next) {
119-
return next(mode, next.executor(), new DetachHandler(new SingleHandler(next.pipeline())));
121+
private static Handler single(ExecutionMode mode, RouteImpl next) {
122+
return next(mode, next.executor(), new DetachHandler(new SingleHandler(next.pipeline())),
123+
false);
120124
}
121125

122-
private static Handler maybe(Mode mode, RouteImpl next) {
123-
return next(mode, next.executor(), new DetachHandler(new MaybeHandler(next.pipeline())));
126+
private static Handler maybe(ExecutionMode mode, RouteImpl next) {
127+
return next(mode, next.executor(), new DetachHandler(new MaybeHandler(next.pipeline())), false);
124128
}
125129

126-
private static Handler next(Mode mode, Executor executor, Handler handler) {
130+
private static Handler next(ExecutionMode mode, Executor executor, Handler handler, boolean blocking) {
127131
if (executor == null) {
128-
return mode == Mode.WORKER ? new WorkerHandler(handler) : handler;
132+
if (mode == ExecutionMode.WORKER) {
133+
return new WorkerHandler(handler);
134+
}
135+
if (mode == ExecutionMode.DEFAULT && blocking) {
136+
return new WorkerHandler(handler);
137+
}
138+
return handler;
129139
}
130-
return new ExecutorHandler(handler, executor);
140+
return new WorkerExecHandler(handler, executor);
131141
}
132142

133143
private static Optional<Class> loadClass(ClassLoader loader, String name) {

future/src/main/java/io/jooby/internal/RouterImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import io.jooby.BaseContext;
55
import io.jooby.Context;
66
import io.jooby.Err;
7-
import io.jooby.Mode;
7+
import io.jooby.ExecutionMode;
88
import io.jooby.Renderer;
99
import io.jooby.Route;
1010
import io.jooby.Router;
@@ -275,7 +275,7 @@ private Route route(@Nonnull String method, @Nonnull String pattern,
275275
if (err == null) {
276276
err = Route.ErrorHandler.DEFAULT;
277277
}
278-
Mode mode = owner.mode();
278+
ExecutionMode mode = owner.mode();
279279
for (Route route : routes) {
280280
RouteImpl routeImpl = (RouteImpl) route;
281281
Executor executor = routeImpl.executor();

future/src/main/java/io/jooby/internal/handler/ExecutorHandler.java renamed to future/src/main/java/io/jooby/internal/handler/WorkerExecHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import javax.annotation.Nonnull;
77
import java.util.concurrent.Executor;
88

9-
public class ExecutorHandler implements ChainedHandler {
9+
public class WorkerExecHandler implements ChainedHandler {
1010
private final Route.Handler next;
1111
private final Executor executor;
1212

13-
public ExecutorHandler(Route.Handler next, Executor executor) {
13+
public WorkerExecHandler(Route.Handler next, Executor executor) {
1414
this.next = next;
1515
this.executor = executor;
1616
}

future/src/main/java/io/jooby/internal/netty/NettyContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ public NettyContext(ChannelHandlerContext ctx, Executor executor,
193193
}
194194

195195
@Nonnull @Override public Context sendStatusCode(int statusCode) {
196+
responseStarted = true;
196197
DefaultFullHttpResponse rsp = new DefaultFullHttpResponse(HTTP_1_1,
197198
HttpResponseStatus.valueOf(statusCode));
198199
rsp.headers().set(CONTENT_LENGTH, 0);

future/src/main/java/io/jooby/jetty/Jetty.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import io.jooby.App;
44
import io.jooby.Functions;
5-
import io.jooby.Mode;
6-
import io.jooby.Router;
75
import io.jooby.internal.jetty.JettyHandler;
86
import io.jooby.internal.jetty.JettyMultiHandler;
97
import org.eclipse.jetty.server.HttpConfiguration;
@@ -15,8 +13,6 @@
1513
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
1614
import org.eclipse.jetty.util.thread.Scheduler;
1715
import org.jooby.funzy.Throwing;
18-
import org.slf4j.Logger;
19-
import org.slf4j.LoggerFactory;
2016

2117
import javax.annotation.Nonnull;
2218
import java.util.ArrayList;

future/src/main/java/io/jooby/netty/Netty.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.jooby.netty;
22

33
import io.jooby.App;
4-
import io.jooby.Mode;
54
import io.jooby.Server;
65
import io.jooby.Functions;
76
import io.jooby.internal.netty.NettyMultiHandler;
@@ -31,9 +30,7 @@
3130
import java.util.LinkedHashMap;
3231
import java.util.List;
3332
import java.util.Map;
34-
import java.util.NoSuchElementException;
3533
import java.util.Optional;
36-
import java.util.concurrent.Executor;
3734

3835
public class Netty implements Server {
3936

future/src/test/java/apps/BenchApp.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import io.jooby.App;
44
import io.jooby.Filters;
5-
import io.jooby.Mode;
5+
import io.jooby.ExecutionMode;
66
import io.jooby.utow.Utow;
77

88
public class BenchApp extends App {
@@ -29,7 +29,7 @@ public Message(String message) {
2929

3030
public static void main(String[] args) {
3131
new Utow()
32-
.deploy(new BenchApp().mode(Mode.EVENT_LOOP))
32+
.deploy(new BenchApp().mode(ExecutionMode.EVENT_LOOP))
3333
.start()
3434
.join();
3535
}

0 commit comments

Comments
 (0)