Search in sources :

Example 1 with KafkaBasedCommandResponseSender

use of org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender in project hono by eclipse.

the class KafkaBasedMappingAndDelegatingCommandHandlerTest method setUp.

/**
 * Sets up fixture.
 */
@BeforeEach
public void setUp() {
    tenantId = UUID.randomUUID().toString();
    deviceId = UUID.randomUUID().toString();
    adapterInstanceId = UUID.randomUUID().toString();
    final TenantClient tenantClient = mock(TenantClient.class);
    when(tenantClient.get(eq(tenantId), any())).thenReturn(Future.succeededFuture(TenantObject.from(tenantId)));
    commandTargetMapper = mock(CommandTargetMapper.class);
    when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId), any())).thenReturn(Future.succeededFuture(createTargetAdapterInstanceJson(deviceId, adapterInstanceId)));
    internalCommandSender = mock(KafkaBasedInternalCommandSender.class);
    when(internalCommandSender.sendCommand(any(CommandContext.class), anyString())).thenReturn(Future.succeededFuture());
    final KafkaBasedCommandResponseSender kafkaBasedCommandResponseSender = mock(KafkaBasedCommandResponseSender.class);
    vertx = mock(Vertx.class);
    final Context context = VertxMockSupport.mockContext(vertx);
    final KafkaCommandProcessingQueue commandQueue = new KafkaCommandProcessingQueue(context);
    final CommandRouterMetrics metrics = mock(CommandRouterMetrics.class);
    when(metrics.startTimer()).thenReturn(Timer.start());
    final Tracer tracer = TracingMockSupport.mockTracer(TracingMockSupport.mockSpan());
    cmdHandler = new KafkaBasedMappingAndDelegatingCommandHandler(vertx, tenantClient, commandQueue, commandTargetMapper, internalCommandSender, kafkaBasedCommandResponseSender, metrics, tracer);
}
Also used : Context(io.vertx.core.Context) CommandContext(org.eclipse.hono.client.command.CommandContext) VertxTestContext(io.vertx.junit5.VertxTestContext) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) KafkaBasedCommandResponseSender(org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender) CommandContext(org.eclipse.hono.client.command.CommandContext) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) Tracer(io.opentracing.Tracer) TenantClient(org.eclipse.hono.client.registry.TenantClient) Vertx(io.vertx.core.Vertx) KafkaBasedInternalCommandSender(org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandSender) BeforeEach(org.junit.jupiter.api.BeforeEach)

Example 2 with KafkaBasedCommandResponseSender

use of org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender in project hono by eclipse.

the class AbstractProtocolAdapterApplication method setCollaborators.

/**
 * Sets collaborators required by all protocol adapters.
 *
 * @param adapter The adapter to set the collaborators on.
 * @throws NullPointerException if adapter is {@code null}
 * @throws IllegalStateException if no connection to the Command Router service has been configured.
 */
protected void setCollaborators(final AbstractProtocolAdapterBase<?> adapter) {
    Objects.requireNonNull(adapter);
    final DeviceRegistrationClient registrationClient = registrationClient();
    final MessagingClientProvider<TelemetrySender> telemetrySenderProvider = new MessagingClientProvider<>();
    final MessagingClientProvider<EventSender> eventSenderProvider = new MessagingClientProvider<>();
    final MessagingClientProvider<CommandResponseSender> commandResponseSenderProvider = new MessagingClientProvider<>();
    final KafkaClientMetricsSupport kafkaClientMetricsSupport = kafkaClientMetricsSupport(kafkaMetricsOptions);
    final var tenantClient = tenantClient();
    if (kafkaEventConfig.isConfigured()) {
        LOG.info("Kafka client configuration present, adding Kafka messaging clients");
        final KafkaProducerFactory<String, Buffer> factory = CachingKafkaProducerFactory.sharedFactory(vertx);
        factory.setMetricsSupport(kafkaClientMetricsSupport);
        telemetrySenderProvider.setClient(new KafkaBasedTelemetrySender(vertx, factory, kafkaTelemetryConfig, protocolAdapterProperties.isDefaultsEnabled(), tracer));
        eventSenderProvider.setClient(new KafkaBasedEventSender(vertx, factory, kafkaEventConfig, protocolAdapterProperties.isDefaultsEnabled(), tracer));
        commandResponseSenderProvider.setClient(new KafkaBasedCommandResponseSender(vertx, factory, kafkaCommandResponseConfig, tracer));
    }
    if (downstreamSenderConfig.isHostConfigured()) {
        telemetrySenderProvider.setClient(downstreamSender());
        eventSenderProvider.setClient(downstreamSender());
        commandResponseSenderProvider.setClient(new ProtonBasedCommandResponseSender(HonoConnection.newConnection(vertx, commandResponseSenderConfig(), tracer), messageSamplerFactory, protocolAdapterProperties.isJmsVendorPropsEnabled()));
    }
    final MessagingClientProviders messagingClientProviders = new MessagingClientProviders(telemetrySenderProvider, eventSenderProvider, commandResponseSenderProvider);
    if (commandRouterConfig.isHostConfigured()) {
        final CommandRouterClient commandRouterClient = commandRouterClient();
        adapter.setCommandRouterClient(commandRouterClient);
        final CommandRouterCommandConsumerFactory commandConsumerFactory = commandConsumerFactory(commandRouterClient);
        if (commandConsumerConfig.isHostConfigured()) {
            commandConsumerFactory.registerInternalCommandConsumer((id, handlers) -> new ProtonBasedInternalCommandConsumer(commandConsumerConnection(), id, handlers));
        }
        final CommandResponseSender kafkaCommandResponseSender = messagingClientProviders.getCommandResponseSenderProvider().getClient(MessagingType.kafka);
        if (kafkaCommandInternalConfig.isConfigured() && kafkaCommandConfig.isConfigured() && kafkaCommandResponseSender != null) {
            commandConsumerFactory.registerInternalCommandConsumer((id, handlers) -> new KafkaBasedInternalCommandConsumer(vertx, kafkaCommandInternalConfig, kafkaCommandConfig, tenantClient, kafkaCommandResponseSender, id, handlers, tracer).setMetricsSupport(kafkaClientMetricsSupport));
        }
        adapter.setCommandConsumerFactory(commandConsumerFactory);
    } else {
        throw new IllegalStateException("No Command Router connection configured");
    }
    adapter.setMessagingClientProviders(messagingClientProviders);
    Optional.ofNullable(connectionEventProducer()).ifPresent(adapter::setConnectionEventProducer);
    adapter.setCredentialsClient(credentialsClient());
    adapter.setHealthCheckServer(healthCheckServer);
    adapter.setRegistrationClient(registrationClient);
    adapter.setResourceLimitChecks(prometheusResourceLimitChecks(resourceLimitChecksConfig, tenantClient));
    adapter.setTenantClient(tenantClient);
    adapter.setTracer(tracer);
}
Also used : Buffer(io.vertx.core.buffer.Buffer) KafkaBasedTelemetrySender(org.eclipse.hono.client.telemetry.kafka.KafkaBasedTelemetrySender) CommandRouterClient(org.eclipse.hono.client.command.CommandRouterClient) ProtonBasedCommandRouterClient(org.eclipse.hono.client.command.amqp.ProtonBasedCommandRouterClient) KafkaBasedCommandResponseSender(org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender) ProtonBasedDeviceRegistrationClient(org.eclipse.hono.client.registry.amqp.ProtonBasedDeviceRegistrationClient) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) ProtonBasedCommandResponseSender(org.eclipse.hono.client.command.amqp.ProtonBasedCommandResponseSender) KafkaBasedEventSender(org.eclipse.hono.client.telemetry.kafka.KafkaBasedEventSender) MicrometerKafkaClientMetricsSupport(org.eclipse.hono.client.kafka.metrics.MicrometerKafkaClientMetricsSupport) KafkaClientMetricsSupport(org.eclipse.hono.client.kafka.metrics.KafkaClientMetricsSupport) NoopKafkaClientMetricsSupport(org.eclipse.hono.client.kafka.metrics.NoopKafkaClientMetricsSupport) CommandRouterCommandConsumerFactory(org.eclipse.hono.client.command.CommandRouterCommandConsumerFactory) MessagingClientProviders(org.eclipse.hono.adapter.MessagingClientProviders) MessagingClientProvider(org.eclipse.hono.client.util.MessagingClientProvider) KafkaBasedInternalCommandConsumer(org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandConsumer) KafkaBasedCommandResponseSender(org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender) ProtonBasedCommandResponseSender(org.eclipse.hono.client.command.amqp.ProtonBasedCommandResponseSender) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) KafkaBasedEventSender(org.eclipse.hono.client.telemetry.kafka.KafkaBasedEventSender) EventSender(org.eclipse.hono.client.telemetry.EventSender) ProtonBasedInternalCommandConsumer(org.eclipse.hono.client.command.amqp.ProtonBasedInternalCommandConsumer) TelemetrySender(org.eclipse.hono.client.telemetry.TelemetrySender) KafkaBasedTelemetrySender(org.eclipse.hono.client.telemetry.kafka.KafkaBasedTelemetrySender)

Example 3 with KafkaBasedCommandResponseSender

use of org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender in project hono by eclipse.

the class KafkaBasedMappingAndDelegatingCommandHandler method mapAndDelegateIncomingCommandMessage.

/**
 * Delegates an incoming command to the protocol adapter instance that the target
 * device is connected to.
 * <p>
 * Determines the target gateway (if applicable) and protocol adapter instance for an incoming command
 * and delegates the command to the resulting protocol adapter instance.
 *
 * @param consumerRecord The consumer record corresponding to the command.
 * @return A future indicating the outcome of the operation.
 * @throws NullPointerException if any of the parameters is {@code null}.
 */
public Future<Void> mapAndDelegateIncomingCommandMessage(final KafkaConsumerRecord<String, Buffer> consumerRecord) {
    Objects.requireNonNull(consumerRecord);
    final Timer.Sample timer = getMetrics().startTimer();
    final KafkaBasedCommand command;
    try {
        command = KafkaBasedCommand.from(consumerRecord);
    } catch (final IllegalArgumentException exception) {
        log.debug("command record is invalid", exception);
        return Future.failedFuture("command record is invalid");
    }
    final SpanContext spanContext = KafkaTracingHelper.extractSpanContext(tracer, consumerRecord);
    final Span currentSpan = createSpan(command.getTenant(), command.getDeviceId(), spanContext);
    KafkaTracingHelper.setRecordTags(currentSpan, consumerRecord);
    final KafkaBasedCommandContext commandContext = new KafkaBasedCommandContext(command, kafkaBasedCommandResponseSender, currentSpan);
    command.logToSpan(currentSpan);
    if (!command.isValid()) {
        log.debug("received invalid command record [{}]", command);
        return tenantClient.get(command.getTenant(), currentSpan.context()).compose(tenantConfig -> {
            commandContext.put(CommandContext.KEY_TENANT_CONFIG, tenantConfig);
            return Future.failedFuture("command is invalid");
        }).onComplete(ar -> {
            commandContext.reject("malformed command message");
            reportInvalidCommand(commandContext, timer);
        }).mapEmpty();
    }
    log.trace("received valid command record [{}]", command);
    commandQueue.add(commandContext);
    final Promise<Void> resultPromise = Promise.promise();
    final long timerId = vertx.setTimer(PROCESSING_TIMEOUT.toMillis(), tid -> {
        if (commandQueue.remove(commandContext) || !commandContext.isCompleted()) {
            log.info("command processing timed out after {}s [{}]", PROCESSING_TIMEOUT.toSeconds(), commandContext.getCommand());
            TracingHelper.logError(commandContext.getTracingSpan(), String.format("command processing timed out after %ds", PROCESSING_TIMEOUT.toSeconds()));
            final ServerErrorException error = new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "command processing timed out");
            commandContext.release(error);
            resultPromise.tryFail(error);
        }
    });
    mapAndDelegateIncomingCommand(commandContext, timer).onComplete(ar -> {
        vertx.cancelTimer(timerId);
        if (ar.failed()) {
            commandQueue.remove(commandContext);
        }
        Futures.tryHandleResult(resultPromise, ar);
    });
    return resultPromise.future();
}
Also used : HttpURLConnection(java.net.HttpURLConnection) KafkaBasedCommandResponseSender(org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender) AbstractMappingAndDelegatingCommandHandler(org.eclipse.hono.commandrouter.impl.AbstractMappingAndDelegatingCommandHandler) MessagingType(org.eclipse.hono.util.MessagingType) Timer(io.micrometer.core.instrument.Timer) KafkaBasedInternalCommandSender(org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandSender) Duration(java.time.Duration) TracingHelper(org.eclipse.hono.tracing.TracingHelper) KafkaTracingHelper(org.eclipse.hono.client.kafka.tracing.KafkaTracingHelper) Futures(org.eclipse.hono.util.Futures) Tracer(io.opentracing.Tracer) KafkaBasedCommand(org.eclipse.hono.client.command.kafka.KafkaBasedCommand) Promise(io.vertx.core.Promise) CommandContext(org.eclipse.hono.client.command.CommandContext) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) TenantClient(org.eclipse.hono.client.registry.TenantClient) Future(io.vertx.core.Future) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) List(java.util.List) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) Buffer(io.vertx.core.buffer.Buffer) KafkaConsumerRecord(io.vertx.kafka.client.consumer.KafkaConsumerRecord) Span(io.opentracing.Span) SpanContext(io.opentracing.SpanContext) Timer(io.micrometer.core.instrument.Timer) KafkaBasedCommand(org.eclipse.hono.client.command.kafka.KafkaBasedCommand) ServerErrorException(org.eclipse.hono.client.ServerErrorException) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) Span(io.opentracing.Span)

Aggregations

KafkaBasedCommandResponseSender (org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender)3 Tracer (io.opentracing.Tracer)2 Vertx (io.vertx.core.Vertx)2 Buffer (io.vertx.core.buffer.Buffer)2 CommandContext (org.eclipse.hono.client.command.CommandContext)2 KafkaBasedCommandContext (org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext)2 KafkaBasedInternalCommandSender (org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandSender)2 TenantClient (org.eclipse.hono.client.registry.TenantClient)2 CommandRouterMetrics (org.eclipse.hono.commandrouter.CommandRouterMetrics)2 CommandTargetMapper (org.eclipse.hono.commandrouter.CommandTargetMapper)2 Timer (io.micrometer.core.instrument.Timer)1 Span (io.opentracing.Span)1 SpanContext (io.opentracing.SpanContext)1 Context (io.vertx.core.Context)1 Future (io.vertx.core.Future)1 Promise (io.vertx.core.Promise)1 VertxTestContext (io.vertx.junit5.VertxTestContext)1 KafkaConsumerRecord (io.vertx.kafka.client.consumer.KafkaConsumerRecord)1 HttpURLConnection (java.net.HttpURLConnection)1 Duration (java.time.Duration)1