use of io.vertx.proton.ProtonSender in project vertx-proton by vert-x3.
the class ProtonSessionImpl method createSender.
@Override
public ProtonSender createSender(String address, ProtonLinkOptions senderOptions) {
Sender sender = session.sender(getOrCreateLinkName(senderOptions));
Symbol[] outcomes = new Symbol[] { Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL, Released.DESCRIPTOR_SYMBOL, Modified.DESCRIPTOR_SYMBOL };
Source source = new Source();
source.setOutcomes(outcomes);
Target target = new Target();
target.setAddress(address);
sender.setSource(source);
sender.setTarget(target);
ProtonSenderImpl s = new ProtonSenderImpl(sender);
if (address == null) {
s.setAnonymousSender(true);
}
s.openHandler((result) -> {
LOG.trace("Sender open completed");
});
s.closeHandler((result) -> {
if (result.succeeded()) {
LOG.trace("Sender closed");
} else {
LOG.warn("Sender closed with error", result.cause());
}
});
// Default to at-least-once
s.setQoS(ProtonQoS.AT_LEAST_ONCE);
return s;
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class AbstractHonoClient method createSender.
/**
* Creates a sender link.
*
* @param ctx The vert.x context to use for establishing the link.
* @param clientConfig The configuration properties to use.
* @param con The connection to create the link for.
* @param targetAddress The target address of the link.
* @param qos The quality of service to use for the link.
* @param closeHook The handler to invoke when the link is closed by the peer (may be {@code null}).
* @return A future for the created link. The future will be completed once the link is open.
* The future will fail with a {@link ServiceInvocationException} if the link cannot be opened.
* @throws NullPointerException if any of the arguments other than close hook is {@code null}.
*/
protected static final Future<ProtonSender> createSender(final Context ctx, final ClientConfigProperties clientConfig, final ProtonConnection con, final String targetAddress, final ProtonQoS qos, final Handler<String> closeHook) {
Objects.requireNonNull(ctx);
Objects.requireNonNull(clientConfig);
Objects.requireNonNull(con);
Objects.requireNonNull(targetAddress);
Objects.requireNonNull(qos);
final Future<ProtonSender> result = Future.future();
ctx.runOnContext(create -> {
final ProtonSender sender = con.createSender(targetAddress);
sender.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.FALSE);
sender.setQoS(qos);
sender.setAutoSettle(true);
sender.openHandler(senderOpen -> {
if (senderOpen.succeeded()) {
LOG.debug("sender open [target: {}, sendQueueFull: {}]", targetAddress, sender.sendQueueFull());
sender.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.TRUE);
// wait on credits a little time, if not already given
if (sender.sendQueueFull()) {
ctx.owner().setTimer(clientConfig.getFlowLatency(), timerID -> {
LOG.debug("sender [target: {}] has {} credits after grace period of {}ms", targetAddress, sender.getCredit(), clientConfig.getFlowLatency());
result.complete(sender);
});
} else {
result.complete(sender);
}
} else {
final ErrorCondition error = sender.getRemoteCondition();
if (error == null) {
LOG.debug("opening sender [{}] failed", targetAddress, senderOpen.cause());
result.fail(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "cannot open sender", senderOpen.cause()));
} else {
LOG.debug("opening sender [{}] failed: {} - {}", targetAddress, error.getCondition(), error.getDescription());
result.fail(StatusCodeMapper.from(error));
}
}
});
sender.detachHandler(remoteDetached -> onRemoteDetach(sender, con.getRemoteContainer(), false, closeHook));
sender.closeHandler(remoteClosed -> onRemoteDetach(sender, con.getRemoteContainer(), true, closeHook));
sender.open();
});
return result;
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class SenderFactoryImplTest method testNewSenderIsClosedOnRemoteDetachOrClose.
@SuppressWarnings({ "unchecked", "rawtypes" })
private void testNewSenderIsClosedOnRemoteDetachOrClose(final TestContext ctx, final BiConsumer<ProtonSender, ArgumentCaptor<Handler>> handlerCaptor) {
// GIVEN a sender created by the factory
final Async senderCreation = ctx.async();
final ProtonSender sender = mock(ProtonSender.class);
when(sender.open()).then(answer -> {
senderCreation.complete();
return sender;
});
final ProtonConnection con = mock(ProtonConnection.class);
final ProtonSession session = mock(ProtonSession.class);
when(session.createSender(anyString())).thenReturn(sender);
final ResourceIdentifier address = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, Constants.DEFAULT_TENANT, null);
final Handler<String> closeHook = mock(Handler.class);
final SenderFactoryImpl factory = new SenderFactoryImpl();
final ArgumentCaptor<Handler> captor = ArgumentCaptor.forClass(Handler.class);
factory.newSender(con, session, address, ProtonQoS.AT_LEAST_ONCE, drain -> {
}, closeHook);
handlerCaptor.accept(sender, captor);
// WHEN the peer detaches from the sender
captor.getValue().handle(Future.succeededFuture(sender));
// THEN the sender gets closed
verify(sender).close();
// and the close hook is called
verify(closeHook).handle(any());
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class ForwardingTelemetryDownstreamAdapterTest method testProcessMessageForwardsMessageToDownstreamSender.
/**
* Verifies that pre-settled telemetry data uploaded by an upstream client is
* forwarded to the downstream container and is accepted and settled immediately.
*
* @param ctx The test context.
*/
@Test
public void testProcessMessageForwardsMessageToDownstreamSender(final TestContext ctx) {
final UpstreamReceiver client = TestSupport.newClient();
// GIVEN an adapter with a connection to a downstream container
final ProtonSender sender = TestSupport.newMockSender(false);
final ForwardingTelemetryDownstreamAdapter adapter = new ForwardingTelemetryDownstreamAdapter(vertx, TestSupport.newMockSenderFactory(sender));
adapter.setMetrics(mock(MessagingMetrics.class));
adapter.setDownstreamConnectionFactory(connectionFactory);
adapter.start(Future.future());
adapter.addSender(client, sender);
// WHEN processing a pre-settled telemetry message
final Message msg = ProtonHelper.message(TELEMETRY_MSG_CONTENT);
MessageHelper.addDeviceId(msg, DEVICE_ID);
final ProtonDelivery upstreamDelivery = mock(ProtonDelivery.class);
when(upstreamDelivery.remotelySettled()).thenReturn(Boolean.TRUE);
adapter.processMessage(client, upstreamDelivery, msg);
// THEN the message is being delivered to the downstream container
verify(sender).send(eq(msg));
// and the upstream delivery is settled with the accepted outcome
verify(upstreamDelivery).disposition(any(Accepted.class), eq(Boolean.TRUE));
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class ForwardingTelemetryDownstreamAdapterTest method testProcessMessageDiscardsMessageIfNoCreditIsAvailable.
/**
* Verifies that telemetry data is discarded if no downstream credit is available.
*
* @param ctx The test context.
*/
@SuppressWarnings("unchecked")
@Test
public void testProcessMessageDiscardsMessageIfNoCreditIsAvailable(final TestContext ctx) {
final UpstreamReceiver client = TestSupport.newClient();
final ProtonDelivery upstreamDelivery = mock(ProtonDelivery.class);
when(upstreamDelivery.remotelySettled()).thenReturn(Boolean.FALSE);
// GIVEN an adapter with a connection to a downstream container
ProtonSender sender = TestSupport.newMockSender(false);
when(sender.sendQueueFull()).thenReturn(true);
final ForwardingEventDownstreamAdapter adapter = new ForwardingEventDownstreamAdapter(vertx, newMockSenderFactory(sender));
adapter.setMetrics(mock(MessagingMetrics.class));
adapter.setDownstreamConnectionFactory(TestSupport.newMockConnectionFactory(false));
adapter.start(Future.future());
adapter.addSender(client, sender);
// WHEN processing an event
final Message msg = ProtonHelper.message(TELEMETRY_MSG_CONTENT);
MessageHelper.addDeviceId(msg, DEVICE_ID);
adapter.processMessage(client, upstreamDelivery, msg);
// THEN the the message is accepted
verify(upstreamDelivery).disposition(any(Released.class), eq(Boolean.TRUE));
// but is not delivered to the downstream container
verify(sender, never()).send(any(Message.class), any(Handler.class));
}
Aggregations