Search in sources :

Example 36 with Rejected

use of org.apache.qpid.proton.amqp.messaging.Rejected in project azure-service-bus-java by Azure.

the class CoreMessageSender method onSendComplete.

@Override
public void onSendComplete(final Delivery delivery) {
    final DeliveryState outcome = delivery.getRemoteState();
    final String deliveryTag = new String(delivery.getTag());
    TRACE_LOGGER.debug("Received ack for delivery. path:{}, linkName:{}, deliveryTag:{}, outcome:{}", CoreMessageSender.this.sendPath, this.sendLink.getName(), deliveryTag, outcome);
    final SendWorkItem<Void> pendingSendWorkItem = this.pendingSendsData.remove(deliveryTag);
    if (pendingSendWorkItem != null) {
        if (outcome instanceof Accepted) {
            this.lastKnownLinkError = null;
            this.retryPolicy.resetRetryCount(this.getClientId());
            pendingSendWorkItem.cancelTimeoutTask(false);
            AsyncUtil.completeFuture(pendingSendWorkItem.getWork(), null);
        } else if (outcome instanceof Rejected) {
            Rejected rejected = (Rejected) outcome;
            ErrorCondition error = rejected.getError();
            Exception exception = ExceptionUtil.toException(error);
            if (ExceptionUtil.isGeneralError(error.getCondition())) {
                this.lastKnownLinkError = exception;
                this.lastKnownErrorReportedAt = Instant.now();
            }
            Duration retryInterval = this.retryPolicy.getNextRetryInterval(this.getClientId(), exception, pendingSendWorkItem.getTimeoutTracker().remaining());
            if (retryInterval == null) {
                this.cleanupFailedSend(pendingSendWorkItem, exception);
            } else {
                TRACE_LOGGER.warn("Send failed for delivery '{}'. Will retry after '{}'", deliveryTag, retryInterval);
                pendingSendWorkItem.setLastKnownException(exception);
                Timer.schedule(() -> {
                    CoreMessageSender.this.reSendAsync(deliveryTag, pendingSendWorkItem, false);
                }, retryInterval, TimerType.OneTimeRun);
            }
        } else if (outcome instanceof Released) {
            this.cleanupFailedSend(pendingSendWorkItem, new OperationCancelledException(outcome.toString()));
        } else {
            this.cleanupFailedSend(pendingSendWorkItem, new ServiceBusException(false, outcome.toString()));
        }
    } else {
        TRACE_LOGGER.warn("Delivery mismatch. path:{}, linkName:{}, delivery:{}", this.sendPath, this.sendLink.getName(), deliveryTag);
    }
}
Also used : Released(org.apache.qpid.proton.amqp.messaging.Released) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Duration(java.time.Duration) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) IOException(java.io.IOException)

Example 37 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 38 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 39 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 40 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)

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