Search in sources :

Example 11 with ProtonSender

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;
}
Also used : Sender(org.apache.qpid.proton.engine.Sender) ProtonSender(io.vertx.proton.ProtonSender) Target(org.apache.qpid.proton.amqp.messaging.Target) Symbol(org.apache.qpid.proton.amqp.Symbol) Source(org.apache.qpid.proton.amqp.messaging.Source)

Example 12 with ProtonSender

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;
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) ClientErrorException(org.eclipse.hono.client.ClientErrorException)

Example 13 with ProtonSender

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());
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) ProtonConnection(io.vertx.proton.ProtonConnection) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) ProtonSession(io.vertx.proton.ProtonSession) Async(io.vertx.ext.unit.Async) Handler(io.vertx.core.Handler)

Example 14 with ProtonSender

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));
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) Message(org.apache.qpid.proton.message.Message) ProtonDelivery(io.vertx.proton.ProtonDelivery) UpstreamReceiver(org.eclipse.hono.messaging.UpstreamReceiver) MessagingMetrics(org.eclipse.hono.messaging.MessagingMetrics) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) Test(org.junit.Test)

Example 15 with ProtonSender

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));
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) Released(org.apache.qpid.proton.amqp.messaging.Released) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) ForwardingEventDownstreamAdapter(org.eclipse.hono.event.impl.ForwardingEventDownstreamAdapter) Handler(io.vertx.core.Handler) UpstreamReceiver(org.eclipse.hono.messaging.UpstreamReceiver) MessagingMetrics(org.eclipse.hono.messaging.MessagingMetrics) Test(org.junit.Test)

Aggregations

ProtonSender (io.vertx.proton.ProtonSender)22 Handler (io.vertx.core.Handler)11 Message (org.apache.qpid.proton.message.Message)9 Test (org.junit.Test)9 ProtonDelivery (io.vertx.proton.ProtonDelivery)8 ProtonConnection (io.vertx.proton.ProtonConnection)6 MessagingMetrics (org.eclipse.hono.messaging.MessagingMetrics)5 UpstreamReceiver (org.eclipse.hono.messaging.UpstreamReceiver)5 Vertx (io.vertx.core.Vertx)4 Future (io.vertx.core.Future)3 Async (io.vertx.ext.unit.Async)3 ProtonQoS (io.vertx.proton.ProtonQoS)3 ErrorCondition (org.apache.qpid.proton.amqp.transport.ErrorCondition)3 Record (org.apache.qpid.proton.engine.Record)3 Constants (org.eclipse.hono.util.Constants)3 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)3 AsyncResult (io.vertx.core.AsyncResult)2 ProtonClientOptions (io.vertx.proton.ProtonClientOptions)2 ProtonHelper (io.vertx.proton.ProtonHelper)2 ProtonSession (io.vertx.proton.ProtonSession)2