Skip to content

Commit 37956f1

Browse files
committed
output:clean up + concurrent test
1 parent f66ea0f commit 37956f1

File tree

10 files changed

+88
-128
lines changed

10 files changed

+88
-128
lines changed

jooby/src/main/java/io/jooby/internal/output/OutputByteArrayStatic.java

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

jooby/src/main/java/io/jooby/output/ByteBufferedOutputFactory.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import edu.umd.cs.findbugs.annotations.NonNull;
1212
import io.jooby.internal.output.CompositeOutput;
13-
import io.jooby.internal.output.OutputByteArrayStatic;
1413
import io.jooby.internal.output.OutputStatic;
1514
import io.jooby.internal.output.WrappedOutput;
1615

@@ -34,7 +33,7 @@ public Output wrap(@NonNull ByteBuffer buffer) {
3433

3534
@Override
3635
public Output wrap(@NonNull String value, @NonNull Charset charset) {
37-
return new OutputByteArrayStatic(value.getBytes(charset));
36+
return new WrappedOutput(ByteBuffer.wrap(value.getBytes(charset)));
3837
}
3938

4039
@Override
@@ -81,12 +80,12 @@ public Output wrap(@NonNull ByteBuffer buffer) {
8180

8281
@Override
8382
public Output wrap(@NonNull byte[] bytes) {
84-
return new OutputByteArrayStatic(bytes);
83+
return wrap(bytes, 0, bytes.length);
8584
}
8685

8786
@Override
8887
public Output wrap(@NonNull byte[] bytes, int offset, int length) {
89-
return new OutputByteArrayStatic(bytes, offset, length);
88+
return new OutputStatic(ByteBuffer.wrap(bytes, offset, length));
9089
}
9190

9291
@Override

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyByteBufOutput.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,7 @@
1212
import io.jooby.output.BufferedOutput;
1313
import io.netty.buffer.ByteBuf;
1414

15-
public class NettyByteBufOutput implements BufferedOutput, NettyByteBufRef {
16-
17-
private final ByteBuf buffer;
18-
19-
protected NettyByteBufOutput(ByteBuf buffer) {
20-
this.buffer = buffer;
21-
}
15+
public record NettyByteBufOutput(ByteBuf buffer) implements BufferedOutput, NettyByteBufRef {
2216

2317
@Override
2418
@NonNull public BufferedOutput write(byte b) {

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyByteBufRef.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ default void send(Context ctx) {
3737
}
3838

3939
static ByteBuf byteBuf(Output output) {
40-
if (output instanceof NettyByteBufRef netty) {
41-
return netty.byteBuf();
40+
if (output instanceof NettyByteBufRef byteBuf) {
41+
return byteBuf.byteBuf();
4242
} else {
4343
return Unpooled.wrappedBuffer(output.asByteBuffer());
4444
}

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyOutputByteArrayStatic.java

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

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyOutputFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public ByteBufAllocator getAllocator() {
9090

9191
@Override
9292
@NonNull public Output wrap(@NonNull byte[] bytes, int offset, int length) {
93-
return new NettyOutputByteArrayStatic(bytes, offset, length);
93+
return new NettyOutputUnsafeHeapByteBuf(bytes, offset, length);
9494
}
9595

9696
@Override

modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyOutputByteArrayStaticNew.java renamed to modules/jooby-netty/src/main/java/io/jooby/internal/netty/NettyOutputUnsafeHeapByteBuf.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
import io.jooby.Context;
1010
import io.netty.buffer.ByteBuf;
1111

12-
public class NettyOutputByteArrayStaticNew implements NettyByteBufRef {
12+
public class NettyOutputUnsafeHeapByteBuf implements NettyByteBufRef {
1313
private final ByteBuf buf;
1414
private final NettyString contentLength;
1515
private final int length;
1616

17-
protected NettyOutputByteArrayStaticNew(byte[] bytes, int offset, int len) {
17+
protected NettyOutputUnsafeHeapByteBuf(byte[] bytes, int offset, int len) {
1818
this.length = len - offset;
1919
this.buf = new NettyUnsafeHeapByteBuf(this.length, this.length);
2020
this.buf.writeBytes(bytes, offset, length);
@@ -33,7 +33,7 @@ public int size() {
3333
@Override
3434
public void send(Context ctx) {
3535
if (ctx.getClass() == NettyContext.class) {
36-
((NettyContext) ctx).send(buf.slice(), contentLength);
36+
((NettyContext) ctx).send(buf.slice(0, length), contentLength);
3737
} else {
3838
ctx.send(asByteBuffer());
3939
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package examples;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
import java.util.concurrent.*;
11+
12+
import io.jooby.junit.ServerTest;
13+
import io.jooby.junit.ServerTestRunner;
14+
15+
public class ConcurrentTest {
16+
17+
@ServerTest
18+
public void makeSureBufferWork(ServerTestRunner runner)
19+
throws ExecutionException, InterruptedException {
20+
var payload = "Hello World!";
21+
runner
22+
.define(
23+
app -> {
24+
var outputFactory = app.getOutputFactory();
25+
var message = outputFactory.wrap(payload);
26+
27+
app.get(
28+
"/plaintext",
29+
ctx -> {
30+
return ctx.send(message);
31+
});
32+
})
33+
.ready(
34+
http -> {
35+
http.concurrent(
36+
"/plaintext",
37+
20,
38+
rsp -> {
39+
assertEquals(payload, rsp.body().string());
40+
});
41+
});
42+
}
43+
}

tests/src/test/java/examples/Performance.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import io.jooby.Jooby;
1515
import io.jooby.ServerOptions;
1616
import io.jooby.StartupSummary;
17-
import io.jooby.netty.NettyServer;
17+
import io.jooby.jetty.JettyServer;
1818

1919
public class Performance extends Jooby {
2020

@@ -43,6 +43,6 @@ public class Performance extends Jooby {
4343

4444
public static void main(final String[] args) {
4545
System.setProperty("io.netty.disableHttpHeadersValidation", "true");
46-
runApp(args, new NettyServer(new ServerOptions()), EVENT_LOOP, Performance::new);
46+
runApp(args, new JettyServer(new ServerOptions()), EVENT_LOOP, Performance::new);
4747
}
4848
}

tests/src/test/java/io/jooby/test/WebClient.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import java.security.cert.X509Certificate;
1515
import java.util.ArrayList;
1616
import java.util.List;
17-
import java.util.concurrent.BlockingQueue;
18-
import java.util.concurrent.CountDownLatch;
19-
import java.util.concurrent.LinkedBlockingQueue;
20-
import java.util.concurrent.TimeUnit;
17+
import java.util.concurrent.*;
2118
import java.util.concurrent.atomic.AtomicBoolean;
2219
import java.util.function.BiConsumer;
2320
import java.util.function.Consumer;
@@ -34,12 +31,7 @@
3431
import io.jooby.ServerSentMessage;
3532
import io.jooby.SneakyThrows;
3633
import io.jooby.WebSocketCloseStatus;
37-
import okhttp3.Headers;
38-
import okhttp3.OkHttpClient;
39-
import okhttp3.RequestBody;
40-
import okhttp3.Response;
41-
import okhttp3.WebSocket;
42-
import okhttp3.WebSocketListener;
34+
import okhttp3.*;
4335
import okhttp3.sse.EventSource;
4436
import okhttp3.sse.EventSourceListener;
4537
import okhttp3.sse.EventSources;
@@ -176,12 +168,16 @@ public WebClient(String scheme, int port, boolean followRedirects) {
176168
try {
177169
this.scheme = scheme;
178170
this.port = port;
171+
Dispatcher dispatcher = new Dispatcher();
172+
dispatcher.setMaxRequests(100); // Maximum 20 concurrent requests overall
173+
dispatcher.setMaxRequestsPerHost(100);
179174
OkHttpClient.Builder builder =
180175
new OkHttpClient.Builder()
181176
.connectTimeout(5, TimeUnit.MINUTES)
182177
.writeTimeout(5, TimeUnit.MINUTES)
183178
.readTimeout(5, TimeUnit.MINUTES)
184-
.followRedirects(followRedirects);
179+
.followRedirects(followRedirects)
180+
.dispatcher(dispatcher);
185181
if (scheme.equalsIgnoreCase("https")) {
186182
configureSelfSigned(builder);
187183
}
@@ -229,6 +225,32 @@ public Request get(String path) {
229225
return invoke("GET", path, null);
230226
}
231227

228+
public void concurrent(String path, int concurrency, SneakyThrows.Consumer<Response> callback) {
229+
var futures = new ArrayList<Future<String>>();
230+
try (var executor = Executors.newFixedThreadPool(concurrency + 5)) {
231+
for (var i = 0; i < concurrency; i++) {
232+
futures.add(
233+
executor.submit(
234+
() -> {
235+
okhttp3.Request.Builder req = new okhttp3.Request.Builder();
236+
req.url(scheme + "://localhost:" + port + path);
237+
new Request(req).execute(callback);
238+
return "OK";
239+
}));
240+
}
241+
for (Future<String> future : futures) {
242+
try {
243+
var result = future.get();
244+
if (!"OK".equals(result)) {
245+
throw new IllegalStateException(result);
246+
}
247+
} catch (Exception e) {
248+
SneakyThrows.propagate(e);
249+
}
250+
}
251+
}
252+
}
253+
232254
public ServerSentMessageIterator sse(String path) {
233255
okhttp3.Request.Builder req = new okhttp3.Request.Builder();
234256
setRequestHeaders(req);

0 commit comments

Comments
 (0)