Search in sources :

Example 46 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project hono by eclipse.

the class ProtonBasedInternalCommandSender method sendCommand.

@Override
public Future<Void> sendCommand(final CommandContext commandContext, final String adapterInstanceId) {
    Objects.requireNonNull(commandContext);
    Objects.requireNonNull(adapterInstanceId);
    return getOrCreateSenderLink(getTargetAddress(adapterInstanceId)).recover(thr -> Future.failedFuture(StatusCodeMapper.toServerError(thr))).compose(sender -> {
        final Span span = newChildSpan(commandContext.getTracingContext(), "delegate Command request");
        final Command command = commandContext.getCommand();
        final Message message = adoptOrCreateMessage(command);
        TracingHelper.setDeviceTags(span, command.getTenant(), command.getDeviceId());
        if (command.isTargetedAtGateway()) {
            MessageHelper.addProperty(message, MessageHelper.APP_PROPERTY_CMD_VIA, command.getGatewayId());
            TracingHelper.TAG_GATEWAY_ID.set(span, command.getGatewayId());
        }
        return sender.sendAndWaitForRawOutcome(message, span);
    }).map(delivery -> {
        final DeliveryState remoteState = delivery.getRemoteState();
        LOG.trace("command [{}] sent to downstream peer; remote state of delivery: {}", commandContext.getCommand(), remoteState);
        if (Accepted.class.isInstance(remoteState)) {
            commandContext.accept();
        } else if (Rejected.class.isInstance(remoteState)) {
            final Rejected rejected = (Rejected) remoteState;
            commandContext.reject(Optional.ofNullable(rejected.getError()).map(ErrorCondition::getDescription).orElse(null));
        } else if (Released.class.isInstance(remoteState)) {
            commandContext.release();
        } else if (Modified.class.isInstance(remoteState)) {
            final Modified modified = (Modified) remoteState;
            commandContext.modify(modified.getDeliveryFailed(), modified.getUndeliverableHere());
        }
        return (Void) null;
    }).onFailure(thr -> {
        LOG.debug("failed to send command [{}] to downstream peer", commandContext.getCommand(), thr);
        if (thr instanceof NoConsumerException) {
            TracingHelper.logError(commandContext.getTracingSpan(), "no credit - target adapter instance '" + adapterInstanceId + "' may be offline in which case the device hasn't subscribed again yet");
        }
        commandContext.release(thr);
    });
}
Also used : InternalCommandSender(org.eclipse.hono.client.command.InternalCommandSender) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Command(org.eclipse.hono.client.command.Command) LoggerFactory(org.slf4j.LoggerFactory) NoConsumerException(org.eclipse.hono.client.NoConsumerException) Modified(org.apache.qpid.proton.amqp.messaging.Modified) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) Message(org.apache.qpid.proton.message.Message) TracingHelper(org.eclipse.hono.tracing.TracingHelper) HonoConnection(org.eclipse.hono.client.HonoConnection) CommandConstants(org.eclipse.hono.util.CommandConstants) Logger(org.slf4j.Logger) CommandContext(org.eclipse.hono.client.command.CommandContext) ProtonHelper(io.vertx.proton.ProtonHelper) MessageHelper(org.eclipse.hono.util.MessageHelper) Released(org.apache.qpid.proton.amqp.messaging.Released) Future(io.vertx.core.Future) Objects(java.util.Objects) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) SenderCachingServiceClient(org.eclipse.hono.client.amqp.SenderCachingServiceClient) Optional(java.util.Optional) Span(io.opentracing.Span) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) Released(org.apache.qpid.proton.amqp.messaging.Released) Modified(org.apache.qpid.proton.amqp.messaging.Modified) Message(org.apache.qpid.proton.message.Message) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) Command(org.eclipse.hono.client.command.Command) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) NoConsumerException(org.eclipse.hono.client.NoConsumerException) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Span(io.opentracing.Span) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted)

Example 47 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project hono by eclipse.

the class ProtonBasedCommandRouterClientTest method testUnregisterCommandConsumerFailsWithRejectedRequest.

/**
 * Verifies that a client invocation of the <em>unregister-command-consumer</em> operation fails
 * if the command router service cannot be reached.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testUnregisterCommandConsumerFailsWithRejectedRequest(final VertxTestContext ctx) {
    // GIVEN a remote peer returning a Rejected disposition
    final ProtonDelivery update = mock(ProtonDelivery.class);
    when(update.getRemoteState()).thenReturn(new Rejected());
    when(update.remotelySettled()).thenReturn(true);
    when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenAnswer(invocation -> {
        final Handler<ProtonDelivery> dispositionHandler = invocation.getArgument(1);
        dispositionHandler.handle(update);
        return mock(ProtonDelivery.class);
    });
    // WHEN unregistering the command consumer
    client.unregisterCommandConsumer("tenant", "deviceId", "adapterInstanceId", span.context()).onComplete(ctx.failing(t -> {
        ctx.verify(() -> {
            assertThat(ServiceInvocationException.extractStatusCode(t)).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
            // THEN the invocation fails and the span is marked as erroneous
            verify(span).setTag(eq(Tags.ERROR.getKey()), eq(Boolean.TRUE));
            // and the span is finished
            verify(span).finish();
        });
        ctx.completeNow();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Tags(io.opentracing.tag.Tags) Timeout(io.vertx.junit5.Timeout) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Duration(java.time.Duration) Map(java.util.Map) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) JsonObject(io.vertx.core.json.JsonObject) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) List(java.util.List) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) ArgumentMatchers.longThat(org.mockito.ArgumentMatchers.longThat) Mockito.mock(org.mockito.Mockito.mock) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) IntStream(java.util.stream.IntStream) CacheDirective(org.eclipse.hono.util.CacheDirective) VertxTestContext(io.vertx.junit5.VertxTestContext) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) AmqpClientUnitTestHelper(org.eclipse.hono.client.amqp.test.AmqpClientUnitTestHelper) CommandRouterConstants(org.eclipse.hono.util.CommandRouterConstants) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArgumentCaptor(org.mockito.ArgumentCaptor) Message(org.apache.qpid.proton.message.Message) LinkedList(java.util.LinkedList) HonoConnection(org.eclipse.hono.client.HonoConnection) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) CommandRouterAction(org.eclipse.hono.util.CommandRouterConstants.CommandRouterAction) Tracer(io.opentracing.Tracer) Vertx(io.vertx.core.Vertx) Mockito.times(org.mockito.Mockito.times) ProtonHelper(io.vertx.proton.ProtonHelper) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Clock(java.time.Clock) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) Handler(io.vertx.core.Handler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Test(org.junit.jupiter.api.Test)

Example 48 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project hono by eclipse.

the class ProtonBasedInternalCommandConsumer method handleCommandMessage.

void handleCommandMessage(final ProtonDelivery delivery, final Message msg) {
    final ProtonBasedCommand command;
    try {
        command = ProtonBasedCommand.fromRoutedCommandMessage(msg);
    } catch (final IllegalArgumentException e) {
        log.debug("address of command message is invalid: {}", msg.getAddress());
        final Rejected rejected = new Rejected();
        rejected.setError(new ErrorCondition(Constants.AMQP_BAD_REQUEST, "invalid command target address"));
        delivery.disposition(rejected, true);
        return;
    }
    final CommandHandlerWrapper commandHandler = commandHandlers.getCommandHandler(command.getTenant(), command.getGatewayOrDeviceId());
    if (commandHandler != null && commandHandler.getGatewayId() != null) {
        // Gateway information set in command handler means a gateway has subscribed for commands for a specific device.
        // This information isn't getting set in the message (by the Command Router) and therefore has to be adopted manually here.
        command.setGatewayId(commandHandler.getGatewayId());
    }
    final SpanContext spanContext = TracingHelper.extractSpanContext(tracer, msg);
    final SpanContext followsFromSpanContext = commandHandler != null ? commandHandler.getConsumerCreationSpanContext() : null;
    final Span currentSpan = CommandContext.createSpan(tracer, command, spanContext, followsFromSpanContext, getClass().getSimpleName());
    currentSpan.setTag(MessageHelper.APP_PROPERTY_ADAPTER_INSTANCE_ID, adapterInstanceId);
    final CommandContext commandContext = new ProtonBasedCommandContext(command, delivery, currentSpan);
    if (commandHandler != null) {
        log.trace("using [{}] for received command [{}]", commandHandler, command);
        // command.isValid() check not done here - it is to be done in the command handler
        commandHandler.handleCommand(commandContext);
    } else {
        log.info("no command handler found for command [{}]", command);
        commandContext.release(new NoConsumerException("no command handler found for command"));
    }
}
Also used : SpanContext(io.opentracing.SpanContext) CommandContext(org.eclipse.hono.client.command.CommandContext) CommandHandlerWrapper(org.eclipse.hono.client.command.CommandHandlerWrapper) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) NoConsumerException(org.eclipse.hono.client.NoConsumerException) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Span(io.opentracing.Span)

Example 49 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project hono by eclipse.

the class ProtonBasedCommandRouterClientTest method testSetLastKnownGatewaysFailsWithRejectedRequest.

/**
 * Verifies that a client invocation of the <em>set-last-known-gateway</em> operation fails
 * if the command router service cannot be reached.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testSetLastKnownGatewaysFailsWithRejectedRequest(final VertxTestContext ctx) {
    // GIVEN a remote peer returning a Rejected disposition
    final ProtonDelivery update = mock(ProtonDelivery.class);
    when(update.getRemoteState()).thenReturn(new Rejected());
    when(update.remotelySettled()).thenReturn(true);
    when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenAnswer(invocation -> {
        final Handler<ProtonDelivery> dispositionHandler = invocation.getArgument(1);
        dispositionHandler.handle(update);
        return mock(ProtonDelivery.class);
    });
    // WHEN setting last known gateway information
    client.setLastKnownGateways("tenant", Map.of("deviceId", "gatewayId"), span.context()).onComplete(ctx.failing(t -> {
        ctx.verify(() -> {
            assertThat(ServiceInvocationException.extractStatusCode(t)).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
            // THEN the invocation fails and the span is marked as erroneous
            verify(span).setTag(eq(Tags.ERROR.getKey()), eq(Boolean.TRUE));
            // and the span is finished
            verify(span).finish();
        });
        ctx.completeNow();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Tags(io.opentracing.tag.Tags) Timeout(io.vertx.junit5.Timeout) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Duration(java.time.Duration) Map(java.util.Map) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) JsonObject(io.vertx.core.json.JsonObject) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) List(java.util.List) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) ArgumentMatchers.longThat(org.mockito.ArgumentMatchers.longThat) Mockito.mock(org.mockito.Mockito.mock) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) IntStream(java.util.stream.IntStream) CacheDirective(org.eclipse.hono.util.CacheDirective) VertxTestContext(io.vertx.junit5.VertxTestContext) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) AmqpClientUnitTestHelper(org.eclipse.hono.client.amqp.test.AmqpClientUnitTestHelper) CommandRouterConstants(org.eclipse.hono.util.CommandRouterConstants) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArgumentCaptor(org.mockito.ArgumentCaptor) Message(org.apache.qpid.proton.message.Message) LinkedList(java.util.LinkedList) HonoConnection(org.eclipse.hono.client.HonoConnection) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) CommandRouterAction(org.eclipse.hono.util.CommandRouterConstants.CommandRouterAction) Tracer(io.opentracing.Tracer) Vertx(io.vertx.core.Vertx) Mockito.times(org.mockito.Mockito.times) ProtonHelper(io.vertx.proton.ProtonHelper) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Clock(java.time.Clock) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) Handler(io.vertx.core.Handler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Test(org.junit.jupiter.api.Test)

Example 50 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project hono by eclipse.

the class RequestResponseClientTest method testCreateAndSendRequestFailsOnRejectedMessage.

private void testCreateAndSendRequestFailsOnRejectedMessage(final VertxTestContext ctx, final Symbol errorCondition, final Consumer<Throwable> failureAssertions) {
    // WHEN sending a request message with some headers and payload
    final JsonObject payload = new JsonObject().put("key", "value");
    client.compose(c -> c.createAndSendRequest("get", null, payload.toBuffer(), "application/json", SimpleRequestResponseResult::from, span)).onComplete(ctx.failing(t -> {
        ctx.verify(() -> {
            // THEN the result handler is failed with the expected error
            failureAssertions.accept(t);
            verify(sample).completed(isA(Rejected.class));
            // and a timer has been set to time out the request
            final ArgumentCaptor<Handler<Long>> timeoutHandlerCaptor = VertxMockSupport.argumentCaptorHandler();
            verify(vertx).setTimer(eq(clientConfig.getRequestTimeout()), timeoutHandlerCaptor.capture());
            // triggering the timer now that the request has been handled should not invoke the sampler timeout method
            timeoutHandlerCaptor.getValue().handle(1L);
            verify(sample, never()).timeout();
        });
        ctx.completeNow();
    }));
    // and the peer rejects the message
    final Rejected rejected = new Rejected();
    rejected.setError(ProtonHelper.condition(errorCondition, "request message cannot be processed"));
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    when(delivery.getRemoteState()).thenReturn(rejected);
    final ArgumentCaptor<Handler<ProtonDelivery>> dispositionHandlerCaptor = VertxMockSupport.argumentCaptorHandler();
    verify(sender).send(any(Message.class), dispositionHandlerCaptor.capture());
    dispositionHandlerCaptor.getValue().handle(delivery);
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Timeout(io.vertx.junit5.Timeout) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Map(java.util.Map) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) JsonObject(io.vertx.core.json.JsonObject) AmqpError(org.apache.qpid.proton.amqp.transport.AmqpError) Data(org.apache.qpid.proton.amqp.messaging.Data) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) Buffer(io.vertx.core.buffer.Buffer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) Mockito.mock(org.mockito.Mockito.mock) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) VertxTestContext(io.vertx.junit5.VertxTestContext) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) AmqpClientUnitTestHelper(org.eclipse.hono.client.amqp.test.AmqpClientUnitTestHelper) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) ArgumentCaptor(org.mockito.ArgumentCaptor) Symbol(org.apache.qpid.proton.amqp.Symbol) Message(org.apache.qpid.proton.message.Message) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) HonoConnection(org.eclipse.hono.client.HonoConnection) ArgumentMatchers.isA(org.mockito.ArgumentMatchers.isA) RequestResponseClientConfigProperties(org.eclipse.hono.client.RequestResponseClientConfigProperties) Tracer(io.opentracing.Tracer) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) ProtonHelper(io.vertx.proton.ProtonHelper) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Mockito.never(org.mockito.Mockito.never) ResourceLimitExceededException(org.eclipse.hono.client.ResourceLimitExceededException) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) Handler(io.vertx.core.Handler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ArgumentCaptor(org.mockito.ArgumentCaptor) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) JsonObject(io.vertx.core.json.JsonObject) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Handler(io.vertx.core.Handler) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected)

Aggregations

Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)59 Message (org.apache.qpid.proton.message.Message)32 ProtonDelivery (io.vertx.proton.ProtonDelivery)28 Handler (io.vertx.core.Handler)27 DeliveryState (org.apache.qpid.proton.amqp.transport.DeliveryState)23 ErrorCondition (org.apache.qpid.proton.amqp.transport.ErrorCondition)23 Accepted (org.apache.qpid.proton.amqp.messaging.Accepted)21 Span (io.opentracing.Span)19 Test (org.junit.jupiter.api.Test)19 ProtonHelper (io.vertx.proton.ProtonHelper)18 ProtonSender (io.vertx.proton.ProtonSender)18 Released (org.apache.qpid.proton.amqp.messaging.Released)18 Future (io.vertx.core.Future)17 HttpURLConnection (java.net.HttpURLConnection)17 MessageHelper (org.eclipse.hono.util.MessageHelper)17 ProtonQoS (io.vertx.proton.ProtonQoS)16 ClientErrorException (org.eclipse.hono.client.ClientErrorException)16 ProtonReceiver (io.vertx.proton.ProtonReceiver)15 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)15 Truth.assertThat (com.google.common.truth.Truth.assertThat)14