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);
}
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);
}
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();
}
Aggregations