use of org.reactivestreams.Subscriber in project vertx-proton by vert-x3.
the class ProtonPublisherIntTest method testMaxOutstandingCredit2.
@Test(timeout = 20000)
public void testMaxOutstandingCredit2(TestContext context) throws Exception {
server.close();
final int maxOutstandingCredit = 20;
final int totalRequests = 107;
final Async receivedMessagesAsync = context.async();
AtomicInteger receivedCredits = new AtomicInteger();
AtomicInteger maxCredits = new AtomicInteger();
AtomicInteger counter = new AtomicInteger();
ProtonServer protonServer = null;
try {
protonServer = createServer((serverConnection) -> {
serverConnection.openHandler(result -> {
serverConnection.open();
});
serverConnection.sessionOpenHandler(session -> session.open());
serverConnection.senderOpenHandler(serverSender -> {
LOG.trace("Server sender opened");
serverSender.open();
AtomicInteger msgNum = new AtomicInteger();
serverSender.sendQueueDrainHandler(s -> {
int credit = serverSender.getCredit();
LOG.trace("Server credit: " + credit);
int max = maxCredits.get();
if (credit > max) {
maxCredits.compareAndSet(max, credit);
}
while (!serverSender.sendQueueFull()) {
serverSender.send(message(String.valueOf(msgNum.incrementAndGet())));
}
// Simple count, only works because of the thread model and using all credits as received
receivedCredits.addAndGet(credit);
});
});
});
// ===== Client Handling =====
ProtonClient client = ProtonClient.create(vertx);
client.connect("localhost", protonServer.actualPort(), res -> {
context.assertTrue(res.succeeded());
ProtonConnection connection = res.result();
connection.open();
// Create publisher with set maxOutstanding
ProtonPublisherOptions options = new ProtonPublisherOptions().setMaxOutstandingCredit(maxOutstandingCredit);
ProtonPublisher<Delivery> publisher = ProtonStreams.createDeliveryConsumer(connection, "myAddress", options);
publisher.subscribe(new Subscriber<Delivery>() {
Subscription sub = null;
@Override
public void onSubscribe(Subscription s) {
LOG.trace("Flowing initial credit");
sub = s;
sub.request(totalRequests);
}
@Override
public void onNext(Delivery d) {
int count = counter.incrementAndGet();
validateMessage(context, count, String.valueOf(count), d.message());
if (count >= totalRequests) {
receivedMessagesAsync.complete();
}
}
@Override
public void onError(Throwable t) {
if (!receivedMessagesAsync.isCompleted()) {
context.fail("onError called");
}
}
@Override
public void onComplete() {
context.fail("onComplete called");
}
});
});
// Verify the max outstanding was honoured and messages were all received as expected
receivedMessagesAsync.awaitSuccess();
context.assertEquals(maxCredits.get(), maxOutstandingCredit, "Unexpected max credit");
context.assertEquals(receivedCredits.get(), totalRequests, "Unexpected total credits received");
} finally {
if (protonServer != null) {
protonServer.close();
}
}
}
use of org.reactivestreams.Subscriber in project vertx-proton by vert-x3.
the class ProtonPublisherIntTest method testAlternativeDispositionStates.
@Test(timeout = 20000)
public void testAlternativeDispositionStates(TestContext context) throws Exception {
server.close();
final Async receivedMessagesAsync = context.async();
final Async ackedMessagesAsync = context.async();
int messageCount = 4;
List<DeliveryState> deliveryStates = Collections.synchronizedList(new ArrayList<>());
List<Delivery> deliveries = Collections.synchronizedList(new ArrayList<>());
AtomicInteger msgNum = new AtomicInteger(1);
ProtonServer protonServer = null;
try {
protonServer = createServer((serverConnection) -> {
serverConnection.openHandler(result -> {
serverConnection.open();
});
serverConnection.sessionOpenHandler(session -> session.open());
serverConnection.senderOpenHandler(serverSender -> {
LOG.trace("Server sender opened");
serverSender.open();
serverSender.sendQueueDrainHandler(s -> {
for (int i = msgNum.get(); i <= messageCount; i = msgNum.incrementAndGet()) {
int j = i;
serverSender.send(message(String.valueOf(i)), del -> {
LOG.trace("Server received disposition for msg: " + j);
DeliveryState state = del.getRemoteState();
context.assertNotNull(state, "Expected message to have a delivery state");
deliveryStates.add(state);
if (deliveryStates.size() == messageCount) {
ackedMessagesAsync.complete();
}
});
}
});
});
});
// ===== Client Handling =====
AtomicInteger counter = new AtomicInteger(0);
ProtonClient client = ProtonClient.create(vertx);
client.connect("localhost", protonServer.actualPort(), res -> {
context.assertTrue(res.succeeded());
ProtonConnection connection = res.result();
// Create consumer stream of Delivery, which must be manually accepted
ProtonPublisher<Delivery> publisher = ProtonStreams.createDeliveryConsumer(connection, "myAddress");
publisher.subscribe(new Subscriber<Delivery>() {
Subscription sub = null;
@Override
public void onSubscribe(Subscription s) {
sub = s;
LOG.trace("Flowing initial credit");
sub.request(messageCount);
}
@Override
public void onNext(Delivery d) {
int count = counter.incrementAndGet();
deliveries.add(d);
if (count == messageCount) {
LOG.trace("Got all messages, completing async");
receivedMessagesAsync.complete();
}
}
@Override
public void onError(Throwable t) {
if (!receivedMessagesAsync.isCompleted()) {
context.fail("onError called");
}
}
@Override
public void onComplete() {
context.fail("onComplete called");
}
});
connection.open();
});
receivedMessagesAsync.awaitSuccess();
// Small delay to ensure there is a window for any
// unexpected automatic accept to occur
Thread.sleep(50);
// Verify no messages acked yet
context.assertTrue(deliveryStates.isEmpty(), "Unexpected acks count");
// Ack them all
deliveries.get(0).disposition(Accepted.getInstance(), true);
deliveries.get(1).disposition(Released.getInstance(), true);
deliveries.get(2).disposition(new Rejected(), true);
deliveries.get(3).disposition(new Modified(), true);
ackedMessagesAsync.awaitSuccess();
} finally {
if (protonServer != null) {
protonServer.close();
}
}
// Verify the messages were all acked as expected
context.assertEquals(deliveryStates.size(), messageCount, "Unexpected state count: " + deliveryStates);
context.assertTrue(deliveryStates.get(0) instanceof Accepted, "Unexpected state: " + deliveryStates.get(0));
context.assertTrue(deliveryStates.get(1) instanceof Released, "Unexpected state: " + deliveryStates.get(1));
context.assertTrue(deliveryStates.get(2) instanceof Rejected, "Unexpected state: " + deliveryStates.get(2));
context.assertTrue(deliveryStates.get(3) instanceof Modified, "Unexpected state: " + deliveryStates.get(3));
}
use of org.reactivestreams.Subscriber in project vertx-proton by vert-x3.
the class ProtonPublisherIntTest method testSubscriberErrorOnConnectionEnd.
@Test(timeout = 20000)
public void testSubscriberErrorOnConnectionEnd(TestContext context) throws Exception {
server.close();
final Async clientLinkOpenAsync = context.async();
final Async serverLinkOpenAsync = context.async();
final Async subErroredAsync = context.async();
ProtonServer protonServer = null;
try {
protonServer = createServer((serverConnection) -> {
serverConnection.openHandler(result -> {
serverConnection.open();
});
serverConnection.sessionOpenHandler(session -> session.open());
serverConnection.senderOpenHandler(serverSender -> {
LOG.trace("Server sender opened");
serverSender.open();
serverLinkOpenAsync.complete();
});
});
// ===== Client Handling =====
ProtonClient client = ProtonClient.create(vertx);
client.connect("localhost", protonServer.actualPort(), res -> {
context.assertTrue(res.succeeded());
ProtonConnection connection = res.result();
connection.open();
ProtonPublisher<Delivery> publisher = ProtonStreams.createDeliveryConsumer(connection, "myAddress");
publisher.subscribe(new Subscriber<Delivery>() {
@Override
public void onSubscribe(Subscription s) {
clientLinkOpenAsync.complete();
}
@Override
public void onNext(Delivery e) {
context.fail("onNext called");
}
@Override
public void onError(Throwable t) {
LOG.trace("onError called");
subErroredAsync.complete();
}
@Override
public void onComplete() {
LOG.trace("onComplete called");
context.fail("onComplete called");
}
});
});
serverLinkOpenAsync.awaitSuccess();
clientLinkOpenAsync.awaitSuccess();
context.assertFalse(subErroredAsync.isCompleted());
protonServer.close();
protonServer = null;
subErroredAsync.awaitSuccess();
} finally {
if (protonServer != null) {
protonServer.close();
}
}
}
use of org.reactivestreams.Subscriber in project vertx-proton by vert-x3.
the class ProtonPublisherIntTest method testDelayedInitialRequest.
@Test(timeout = 20000)
public void testDelayedInitialRequest(TestContext context) {
Async async = context.async();
connect(context, connection -> {
connection.open();
AtomicInteger counter = new AtomicInteger(0);
AtomicBoolean initialCreditGranted = new AtomicBoolean();
AtomicBoolean additionalCreditGranted = new AtomicBoolean();
final int delay = 250;
final long startTime = System.currentTimeMillis();
ProtonPublisher<Delivery> publisher = ProtonStreams.createDeliveryConsumer(connection, "two_messages");
publisher.subscribe(new Subscriber<Delivery>() {
Subscription sub = null;
@Override
public void onSubscribe(Subscription s) {
vertx.setTimer(delay, x -> {
LOG.trace("Flowing initial credit");
initialCreditGranted.set(true);
sub = s;
sub.request(1);
});
}
@Override
public void onNext(Delivery d) {
int count = counter.incrementAndGet();
switch(count) {
case 1:
{
validateMessage(context, count, String.valueOf(count), d.message());
context.assertTrue(initialCreditGranted.get(), "Initial credit not yet granted, so we" + " should not have received message 1 yet!");
// Verify lack of initial credit results in delayed receipt of first message.
context.assertTrue(System.currentTimeMillis() > startTime + delay, "Message received before expected time delay elapsed!");
LOG.trace("Got msg 1");
// We only issued 1 credit, so we should not get more
// messages until more credit is flowed, use the
// callback for this msg to do that after further delay
vertx.setTimer(delay, x -> {
LOG.trace("Granting additional credit");
additionalCreditGranted.set(true);
sub.request(1);
});
break;
}
case 2:
{
validateMessage(context, count, String.valueOf(count), d.message());
context.assertTrue(additionalCreditGranted.get(), "Additional credit not yet granted, so we" + " should not have received message " + count + " yet!");
context.assertTrue(System.currentTimeMillis() > startTime + (delay * 2), "Message received before expected time delay elapsed!");
// Got the last message, lets finish the test.
LOG.trace("Got msg 2, completing async");
async.complete();
connection.disconnect();
break;
}
}
}
@Override
public void onError(Throwable t) {
if (!async.isCompleted()) {
context.fail("onError called");
}
}
@Override
public void onComplete() {
context.fail("onComplete called");
}
});
});
}
use of org.reactivestreams.Subscriber in project vertx-proton by vert-x3.
the class TrackerSubscriberBlackboxVerificationTckTest method createSubscriber.
@Override
public Subscriber<Tracker> createSubscriber() {
int actualPort = server.actualPort();
ProtonClient client = ProtonClient.create(vertx);
AtomicReference<Subscriber<Tracker>> ref = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
client.connect("localhost", actualPort, result -> {
if (result.succeeded()) {
ProtonConnection conn = result.result();
conn.open();
ProtonSubscriber<Tracker> stream = ProtonStreams.createTrackerProducer(conn, "myAddress");
((ProtonSubscriberImpl) stream).setEmitOnConnectionEnd(false);
ref.set(stream);
} else {
LOG.error("Connection failed");
}
latch.countDown();
});
try {
LOG.trace("Awaiting connection");
boolean res = latch.await(2, TimeUnit.SECONDS);
LOG.trace("Client connected: " + res);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while creating subscriber", e);
}
return ref.get();
}
Aggregations