use of java.util.concurrent.Flow.Subscription in project helidon by oracle.
the class BufferedEmittingPublisherTest method testHookOnRequested.
@Test
public void testHookOnRequested() {
final AtomicLong requested = new AtomicLong();
BufferedEmittingPublisher<Long> publisher = new BufferedEmittingPublisher<Long>() {
};
publisher.onRequest((n, demand) -> requested.set(n));
TestSubscriber<Long> subscriber = new TestSubscriber<Long>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(1);
}
};
publisher.subscribe(subscriber);
assertThat(requested.get(), is(equalTo(1L)));
}
use of java.util.concurrent.Flow.Subscription in project helidon by oracle.
the class MultiPartDecoderTest method testPartContentSubscriberThrottling.
@Test
public void testPartContentSubscriberThrottling() {
String boundary = "boundary";
final byte[] chunk1 = ("--" + boundary + "\n" + "Content-Id: part1\n" + "\n" + "body 1.aaaa\n").getBytes();
final byte[] chunk2 = "body 1.bbbb\n".getBytes();
final byte[] chunk3 = ("body 1.cccc\n" + "--" + boundary + "\n" + "Content-Id: part2\n" + "\n" + "This is the 2nd").getBytes();
final byte[] chunk4 = ("body.\n" + "--" + boundary + "--").getBytes();
final CountDownLatch latch = new CountDownLatch(3);
Consumer<BodyPart> consumer = (part) -> {
latch.countDown();
if (latch.getCount() == 2) {
assertThat(part.headers().values("Content-Id"), hasItems("part1"));
}
part.content().subscribe(new Subscriber<DataChunk>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(1);
}
@Override
public void onNext(DataChunk item) {
latch.countDown();
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
}
});
};
BodyPartSubscriber testSubscriber = new BodyPartSubscriber(SUBSCRIBER_TYPE.ONE_BY_ONE, consumer);
partsPublisher(boundary, List.of(chunk1, chunk2, chunk3, chunk4)).subscribe(testSubscriber);
waitOnLatchNegative(latch, "the 2nd part should not be processed");
assertThat(latch.getCount(), is(equalTo(1L)));
try {
testSubscriber.complete.orTimeout(200, TimeUnit.MILLISECONDS).join();
throw new IllegalStateException("Not expecting to make progress, unless the part is consumed");
} catch (CompletionException e) {
Throwable error = e.getCause();
// This is the expected outcome - the testSubcriber is not making progress
assertThat(error.getClass(), is(equalTo(TimeoutException.class)));
}
}
use of java.util.concurrent.Flow.Subscription in project helidon by oracle.
the class ContextLifeCycleTest method testContextReactive.
@Test
void testContextReactive() {
Handler handler = (req, res) -> {
String cid = req.context().id();
req.content().subscribe(new Subscriber<>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(Long.MAX_VALUE);
}
@Override
public void onNext(DataChunk item) {
item.release();
if (!cid.equals(contextId())) {
throw new IllegalStateException("Context invalid");
}
}
@Override
public void onError(Throwable throwable) {
res.send(throwable);
}
@Override
public void onComplete() {
if (!cid.equals(contextId())) {
res.send(new IllegalStateException("Context invalid"));
} else {
res.send();
}
}
});
};
WebServer webServer = WebServer.builder(Routing.builder().post(handler)).build().start().await(10, TimeUnit.SECONDS);
ResponseStatus responseStatus = WebClient.builder().baseUri("http://localhost:" + webServer.port()).build().post().submit("some-payload").map(WebClientResponse::status).onTerminate(webServer::shutdown).await(10, TimeUnit.SECONDS);
assertThat(responseStatus.code(), is(200));
}
use of java.util.concurrent.Flow.Subscription in project helidon by oracle.
the class RequestContentTest method multiThreadingFilterAndReaderTest.
@SuppressWarnings("unchecked")
@Test
public void multiThreadingFilterAndReaderTest() throws Exception {
CountDownLatch subscribedLatch = new CountDownLatch(1);
SubmissionPublisher<DataChunk> publisher = new SubmissionPublisher<>(Runnable::run, 10);
ForkJoinPool.commonPool().submit(() -> {
try {
if (!subscribedLatch.await(10, TimeUnit.SECONDS)) {
fail("Subscriber didn't subscribe in timely manner!");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted!", e);
}
publisher.submit(DataChunk.create("first".getBytes()));
publisher.submit(DataChunk.create("second".getBytes()));
publisher.submit(DataChunk.create("third".getBytes()));
publisher.close();
});
Request request = requestTestStub(Multi.create(publisher));
request.content().registerFilter(originalPublisher -> subscriberDelegate -> originalPublisher.subscribe(new Subscriber<DataChunk>() {
@Override
public void onSubscribe(Subscription subscription) {
subscriberDelegate.onSubscribe(subscription);
subscribedLatch.countDown();
}
@Override
public void onNext(DataChunk item) {
// mapping the on next call only
subscriberDelegate.onNext(DataChunk.create(requestChunkAsString(item).toUpperCase().getBytes()));
}
@Override
public void onError(Throwable throwable) {
subscriberDelegate.onError(throwable);
}
@Override
public void onComplete() {
subscriberDelegate.onComplete();
}
}));
request.content().registerReader(Iterable.class, (publisher1, clazz) -> {
fail("Iterable reader should have not been used!");
throw new IllegalStateException("unreachable code");
});
request.content().registerReader(ArrayList.class, (publisher1, clazz) -> {
fail("ArrayList reader should have not been used!");
throw new IllegalStateException("unreachable code");
});
request.content().registerReader(List.class, (publisher1, clazz) -> {
CompletableFuture<List> future = new CompletableFuture<>();
List<String> list = new CopyOnWriteArrayList<>();
publisher1.subscribe(new Subscriber<DataChunk>() {
@Override
public void onSubscribe(Subscription subscription) {
subscription.request(Long.MAX_VALUE);
subscribedLatch.countDown();
}
@Override
public void onNext(DataChunk item) {
list.add(TestUtils.requestChunkAsString(item));
}
@Override
public void onError(Throwable throwable) {
fail("Received an exception: " + throwable.getMessage());
}
@Override
public void onComplete() {
future.complete(list);
}
});
return future;
});
List<String> result = (List<String>) request.content().as(List.class).toCompletableFuture().get(10, TimeUnit.SECONDS);
assertThat(result, hasItems(is("FIRST"), is("SECOND"), is("THIRD")));
}
use of java.util.concurrent.Flow.Subscription in project helidon by oracle.
the class NettyWebServerTest method main.
/**
* Start the test and then run:
* <pre><code>
* seq 1000 | head -c 1000 | curl -X PUT -Ssf http://localhost:8080 --data-binary @- http://localhost:8080 --data ahoj
* </code></pre>
* <p>
*
* @throws InterruptedException if the main thread is interrupted
*/
static void main(String[] args) throws InterruptedException {
WebServer webServer = WebServer.builder().port(8080).host("localhost").routing(routing((breq, bres) -> {
SubmissionPublisher<DataChunk> responsePublisher = new SubmissionPublisher<>(ForkJoinPool.commonPool(), 1024);
responsePublisher.subscribe(bres);
final AtomicReference<Subscription> subscription = new AtomicReference<>();
// Read request and immediately write to response
Multi.create(breq.bodyPublisher()).subscribe((DataChunk chunk) -> {
DataChunk responseChunk = DataChunk.create(true, chunk::release, chunk.data());
responsePublisher.submit(responseChunk);
ForkJoinPool.commonPool().submit(() -> {
try {
Thread.sleep(1);
subscription.get().request(ThreadLocalRandom.current().nextLong(1, 3));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
});
}, (Throwable ex) -> {
LOGGER.log(Level.WARNING, "An error occurred during the flow consumption!", ex);
}, responsePublisher::close, (Subscription s) -> {
subscription.set(s);
s.request(1);
bres.writeStatusAndHeaders(Http.Status.CREATED_201, Collections.emptyMap());
});
})).build();
webServer.start();
Thread.currentThread().join();
}
Aggregations