Skip to content

Commit c5139cd

Browse files
committed
Non-blocking: Improve non-blokcing handling
- Assume app is non-blocking while running in `event loop` mode - Add fallback rendering to non-blocking filter - Adjust handlers to return ctx - Fix test supports
1 parent 13304e3 commit c5139cd

13 files changed

Lines changed: 92 additions & 26 deletions

File tree

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static io.jooby.ReactiveSupport.concurrent;
99
import static io.jooby.internal.handler.DefaultHandler.DEFAULT;
1010
import static io.jooby.internal.handler.DetachHandler.DETACH;
11+
import static io.jooby.internal.handler.SendDirect.DIRECT;
1112
import static io.jooby.internal.handler.WorkerHandler.WORKER;
1213

1314
import java.lang.reflect.Type;
@@ -24,7 +25,6 @@
2425
import io.jooby.Route.Handler;
2526
import io.jooby.internal.handler.DispatchHandler;
2627
import io.jooby.internal.handler.PostDispatchInitializerHandler;
27-
import io.jooby.internal.handler.SendDirect;
2828

2929
public class Pipeline {
3030

@@ -35,6 +35,7 @@ public static Handler build(
3535
ContextInitializer initializer,
3636
Set<ResultHandler> responseHandler) {
3737
// Set default wrapper and blocking mode
38+
route.setReactive(route.isReactive() || isDefaultReactive(executor, mode));
3839
Route.Filter wrapper = route.isReactive() ? DETACH : DEFAULT;
3940

4041
/** Return type is set by annotation processor, or manually per lambda route: */
@@ -43,11 +44,10 @@ public static Handler build(
4344
Class<?> type = Reified.rawType(returnType);
4445
/** Context: */
4546
if (Context.class.isAssignableFrom(type)) {
46-
if (executor == null && mode == ExecutionMode.EVENT_LOOP) {
47-
route.setReactive(true);
47+
if (route.isReactive()) {
4848
wrapper = DETACH;
4949
} else {
50-
wrapper = SendDirect.DIRECT;
50+
wrapper = DIRECT;
5151
}
5252
} else if (CompletionStage.class.isAssignableFrom(type)
5353
|| Flow.Publisher.class.isAssignableFrom(type)) {
@@ -86,6 +86,10 @@ public static Handler build(
8686
mode, executor, decorate(initializer, wrapper.then(pipeline)), route.isReactive());
8787
}
8888

89+
private static boolean isDefaultReactive(Executor executor, ExecutionMode mode) {
90+
return executor == null && mode == ExecutionMode.EVENT_LOOP;
91+
}
92+
8993
private static Handler decorate(ContextInitializer initializer, Handler handler) {
9094
return initializer == null
9195
? handler

jooby/src/main/java/io/jooby/internal/handler/ConcurrentHandler.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ public Route.Handler apply(@NonNull Route.Handler next) {
2323
Object result = next.apply(ctx);
2424
if (result instanceof Flow.Publisher publisher) {
2525
publisher.subscribe(newSubscriber(ctx));
26+
// Return context to mark as handled
27+
return ctx;
2628
} else if (result instanceof CompletionStage future) {
27-
return future.whenComplete(
29+
future.whenComplete(
2830
(value, x) -> {
2931
try {
3032
Route.After after = ctx.getRoute().getAfter();
@@ -42,6 +44,8 @@ public Route.Handler apply(@NonNull Route.Handler next) {
4244
ctx.sendError(cause);
4345
}
4446
});
47+
// Return context to mark as handled
48+
return ctx;
4549
}
4650
return result;
4751
};
@@ -59,4 +63,9 @@ private Throwable unwrap(Throwable x) {
5963
public void setRoute(Route route) {
6064
route.setReactive(true);
6165
}
66+
67+
@Override
68+
public String toString() {
69+
return "concurrent";
70+
}
6271
}

jooby/src/main/java/io/jooby/internal/handler/DefaultHandler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,9 @@ public Route.Handler apply(@NonNull Route.Handler next) {
3030
}
3131
};
3232
}
33+
34+
@Override
35+
public String toString() {
36+
return "default";
37+
}
3338
}

jooby/src/main/java/io/jooby/internal/handler/DetachHandler.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,24 @@ private DetachHandler() {}
1616

1717
@NonNull @Override
1818
public Route.Handler apply(@NonNull Route.Handler next) {
19-
return ctx -> {
20-
return ctx.detach(next);
21-
};
19+
return context ->
20+
context.detach(
21+
(ctx -> {
22+
try {
23+
Object value = next.apply(ctx);
24+
if (value != ctx && !ctx.isResponseStarted()) {
25+
ctx.render(value);
26+
}
27+
return value;
28+
} catch (Throwable cause) {
29+
ctx.sendError(cause);
30+
return cause;
31+
}
32+
}));
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return "detach";
2238
}
2339
}

jooby/src/main/java/io/jooby/internal/handler/DispatchHandler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,9 @@ public Route.Handler apply(@NonNull Route.Handler next) {
3030
}
3131
});
3232
}
33+
34+
@Override
35+
public String toString() {
36+
return "dispatch";
37+
}
3338
}

jooby/src/main/java/io/jooby/internal/handler/SendDirect.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@ public Route.Handler apply(@NonNull Route.Handler next) {
2626
}
2727
};
2828
}
29+
30+
@Override
31+
public String toString() {
32+
return "direct";
33+
}
2934
}

jooby/src/main/java/io/jooby/internal/handler/WorkerHandler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,9 @@ public Route.Handler apply(@NonNull Route.Handler next) {
2525
}
2626
});
2727
}
28+
29+
@Override
30+
public String toString() {
31+
return "worker";
32+
}
2833
}

jooby/src/main/kotlin/io/jooby/CoroutineRouter.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,14 @@ class CoroutineRouter(val coroutineStart: CoroutineStart, val router: Router) {
7474
launch(handlerContext) {
7575
val result = handler(handlerContext)
7676
ctx.route.after?.apply(ctx, result, null)
77-
if (result != ctx) {
77+
if (result != ctx && !ctx.isResponseStarted) {
7878
ctx.render(result)
7979
}
80+
// Return context to mark as handled
81+
ctx
8082
}
83+
// Return context to mark as handled
84+
ctx
8185
}
8286
.setHandle(handler)
8387

modules/jooby-mutiny/src/main/java/io/jooby/mutiny/Mutiny.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,12 @@ public Route.Handler apply(@NonNull Route.Handler next) {
6060
// send error:
6161
ctx.sendError((Throwable) failure);
6262
});
63+
// Return context to mark as handled
64+
return ctx;
6365
} else if (result instanceof Multi multi) {
6466
multi.subscribe(newSubscriber(ctx));
67+
// Return context to mark as handled
68+
return ctx;
6569
}
6670
return result;
6771
};

modules/jooby-reactor/src/main/java/io/jooby/reactor/Reactor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public Route.Handler apply(@NonNull Route.Handler next) {
4848
Object result = next.apply(ctx);
4949
if (result instanceof Flux flux) {
5050
flux.subscribe(toSubscriber(newSubscriber(ctx)));
51+
// Return context to mark as handled
52+
return ctx;
5153
} else if (result instanceof Mono mono) {
5254
mono.subscribe(
5355
value -> {
@@ -62,6 +64,8 @@ public Route.Handler apply(@NonNull Route.Handler next) {
6264
// send error:
6365
ctx.sendError((Throwable) failure);
6466
});
67+
// Return context to mark as handled
68+
return ctx;
6569
}
6670
return result;
6771
};

0 commit comments

Comments
 (0)