Search in sources :

Example 1 with CommandTargetMapper

use of org.eclipse.hono.commandrouter.CommandTargetMapper in project hono by eclipse.

the class KafkaBasedCommandConsumerFactoryImplIT method getKafkaBasedCommandConsumerFactory.

private KafkaBasedCommandConsumerFactoryImpl getKafkaBasedCommandConsumerFactory(final Supplier<Future<Void>> targetAdapterInstanceGetterCompletionFutureSupplier, final String tenantToHandleCommandsFor) {
    final KafkaProducerFactory<String, Buffer> producerFactory = CachingKafkaProducerFactory.sharedFactory(vertx);
    final TenantClient tenantClient = getTenantClient();
    final CommandTargetMapper commandTargetMapper = new CommandTargetMapper() {

        @Override
        public Future<JsonObject> getTargetGatewayAndAdapterInstance(final String tenantId, final String deviceId, final SpanContext context) {
            final JsonObject jsonObject = new JsonObject();
            jsonObject.put(DeviceConnectionConstants.FIELD_ADAPTER_INSTANCE_ID, adapterInstanceId);
            jsonObject.put(DeviceConnectionConstants.FIELD_PAYLOAD_DEVICE_ID, deviceId);
            if (!tenantId.equals(tenantToHandleCommandsFor)) {
                return Future.failedFuture("ignoring command for other tenant " + tenantId);
            }
            if (targetAdapterInstanceGetterCompletionFutureSupplier == null) {
                return Future.succeededFuture(jsonObject);
            }
            return targetAdapterInstanceGetterCompletionFutureSupplier.get().map(jsonObject);
        }
    };
    final Span span = TracingMockSupport.mockSpan();
    final Tracer tracer = TracingMockSupport.mockTracer(span);
    final MessagingKafkaConsumerConfigProperties kafkaConsumerConfig = new MessagingKafkaConsumerConfigProperties();
    kafkaConsumerConfig.setConsumerConfig(Map.of(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, IntegrationTestSupport.DOWNSTREAM_BOOTSTRAP_SERVERS));
    final CommandRouterMetrics metrics = mock(CommandRouterMetrics.class);
    when(metrics.startTimer()).thenReturn(Timer.start());
    final var kafkaBasedCommandConsumerFactoryImpl = new KafkaBasedCommandConsumerFactoryImpl(vertx, tenantClient, commandTargetMapper, producerFactory, IntegrationTestSupport.getKafkaProducerConfig(), IntegrationTestSupport.getKafkaProducerConfig(), kafkaConsumerConfig, metrics, NoopKafkaClientMetricsSupport.INSTANCE, tracer, null);
    kafkaBasedCommandConsumerFactoryImpl.setGroupId(commandRouterGroupId);
    componentsToStopAfterTest.add(kafkaBasedCommandConsumerFactoryImpl);
    return kafkaBasedCommandConsumerFactoryImpl;
}
Also used : Buffer(io.vertx.core.buffer.Buffer) KafkaBasedCommandConsumerFactoryImpl(org.eclipse.hono.commandrouter.impl.kafka.KafkaBasedCommandConsumerFactoryImpl) SpanContext(io.opentracing.SpanContext) Tracer(io.opentracing.Tracer) JsonObject(io.vertx.core.json.JsonObject) Span(io.opentracing.Span) MessagingKafkaConsumerConfigProperties(org.eclipse.hono.client.kafka.consumer.MessagingKafkaConsumerConfigProperties) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) TenantClient(org.eclipse.hono.client.registry.TenantClient)

Example 2 with CommandTargetMapper

use of org.eclipse.hono.commandrouter.CommandTargetMapper in project hono by eclipse.

the class KafkaBasedMappingAndDelegatingCommandHandlerTest method testCommandDelegationOrderWithMappingFailedForFirstEntry.

/**
 * Verifies the behaviour of the
 * {@link KafkaBasedMappingAndDelegatingCommandHandler#mapAndDelegateIncomingCommandMessage(KafkaConsumerRecord)}
 * method in a scenario where the rather long-running processing of a command delays subsequent, already mapped
 * commands from getting delegated to the target adapter instance. After the processing of the first command finally
 * resulted in an error, the subsequent commands shall get delegated in the correct order.
 *
 * @param ctx The vert.x test context
 */
@Test
public void testCommandDelegationOrderWithMappingFailedForFirstEntry(final VertxTestContext ctx) {
    final String deviceId1 = "device1";
    final String deviceId2 = "device2";
    final String deviceId3 = "device3";
    final String deviceId4 = "device4";
    // GIVEN valid command records
    final KafkaConsumerRecord<String, Buffer> commandRecord1 = getCommandRecord(tenantId, deviceId1, "subject1", 0, 1);
    final KafkaConsumerRecord<String, Buffer> commandRecord2 = getCommandRecord(tenantId, deviceId2, "subject2", 0, 2);
    final KafkaConsumerRecord<String, Buffer> commandRecord3 = getCommandRecord(tenantId, deviceId3, "subject3", 0, 3);
    final KafkaConsumerRecord<String, Buffer> commandRecord4 = getCommandRecord(tenantId, deviceId4, "subject4", 0, 4);
    // WHEN getting the target adapter instances for the commands results in different delays for each command
    // so that the invocations are completed with the order: commandRecord3, commandRecord2, commandRecord1 (failed), commandRecord4
    // with command 1 getting failed
    final Promise<JsonObject> resultForCommand1 = Promise.promise();
    when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId1), any())).thenReturn(resultForCommand1.future());
    final Promise<JsonObject> resultForCommand2 = Promise.promise();
    when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId2), any())).thenReturn(resultForCommand2.future());
    final Promise<JsonObject> resultForCommand3 = Promise.promise();
    when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId3), any())).thenReturn(resultForCommand3.future());
    doAnswer(invocation -> {
        resultForCommand3.complete(createTargetAdapterInstanceJson(deviceId3, adapterInstanceId));
        resultForCommand2.complete(createTargetAdapterInstanceJson(deviceId2, adapterInstanceId));
        resultForCommand1.fail("mapping of command 1 failed for some reason");
        return Future.succeededFuture(createTargetAdapterInstanceJson(deviceId4, adapterInstanceId));
    }).when(commandTargetMapper).getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId4), any());
    // WHEN mapping and delegating the commands
    final Future<Void> cmd1Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord1);
    final Future<Void> cmd2Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord2);
    final Future<Void> cmd3Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord3);
    final Future<Void> cmd4Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord4);
    // THEN the messages are delegated in the original order, with command 1 left out because it timed out
    CompositeFuture.all(cmd2Future, cmd3Future, cmd4Future).onComplete(ctx.succeeding(r -> {
        ctx.verify(() -> {
            assertThat(cmd1Future.failed()).isTrue();
            final ArgumentCaptor<CommandContext> commandContextCaptor = ArgumentCaptor.forClass(CommandContext.class);
            verify(internalCommandSender, times(3)).sendCommand(commandContextCaptor.capture(), anyString());
            final List<CommandContext> capturedCommandContexts = commandContextCaptor.getAllValues();
            assertThat(capturedCommandContexts.get(0).getCommand().getDeviceId()).isEqualTo(deviceId2);
            assertThat(capturedCommandContexts.get(1).getCommand().getDeviceId()).isEqualTo(deviceId3);
            assertThat(capturedCommandContexts.get(2).getCommand().getDeviceId()).isEqualTo(deviceId4);
        });
        ctx.completeNow();
    }));
}
Also used : Buffer(io.vertx.core.buffer.Buffer) HttpURLConnection(java.net.HttpURLConnection) BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) KafkaBasedCommandResponseSender(org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender) Context(io.vertx.core.Context) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) KafkaBasedInternalCommandSender(org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandSender) Mockito.doAnswer(org.mockito.Mockito.doAnswer) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) JsonObject(io.vertx.core.json.JsonObject) DeviceConnectionConstants(org.eclipse.hono.util.DeviceConnectionConstants) CommandContext(org.eclipse.hono.client.command.CommandContext) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) UUID(java.util.UUID) TenantClient(org.eclipse.hono.client.registry.TenantClient) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Test(org.junit.jupiter.api.Test) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) KafkaConsumerRecord(io.vertx.kafka.client.consumer.KafkaConsumerRecord) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Optional(java.util.Optional) Mockito.mock(org.mockito.Mockito.mock) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) VertxTestContext(io.vertx.junit5.VertxTestContext) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) CompositeFuture(io.vertx.core.CompositeFuture) ArgumentCaptor(org.mockito.ArgumentCaptor) Timer(io.micrometer.core.instrument.Timer) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) KafkaRecordHelper(org.eclipse.hono.client.kafka.KafkaRecordHelper) Truth.assertThat(com.google.common.truth.Truth.assertThat) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) Mockito.verify(org.mockito.Mockito.verify) TenantObject(org.eclipse.hono.util.TenantObject) HonoTopic(org.eclipse.hono.client.kafka.HonoTopic) Mockito.never(org.mockito.Mockito.never) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) Handler(io.vertx.core.Handler) KafkaHeader(io.vertx.kafka.client.producer.KafkaHeader) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ArgumentCaptor(org.mockito.ArgumentCaptor) CommandContext(org.eclipse.hono.client.command.CommandContext) KafkaBasedCommandContext(org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext) JsonObject(io.vertx.core.json.JsonObject) List(java.util.List) ArrayList(java.util.ArrayList) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Test(org.junit.jupiter.api.Test)

Example 3 with CommandTargetMapper

use of org.eclipse.hono.commandrouter.CommandTargetMapper in project hono by eclipse.

the class ProtonBasedMappingAndDelegatingCommandHandlerTest method setUp.

/**
 * Sets up fixture.
 */
@BeforeEach
public void setUp() {
    final Vertx vertx = mock(Vertx.class);
    final Context context = VertxMockSupport.mockContext(vertx);
    when(vertx.getOrCreateContext()).thenReturn(context);
    doAnswer(invocation -> {
        final Handler<Void> handler = invocation.getArgument(1);
        handler.handle(null);
        return null;
    }).when(vertx).setTimer(anyLong(), VertxMockSupport.anyHandler());
    final EventBus eventBus = mock(EventBus.class);
    when(vertx.eventBus()).thenReturn(eventBus);
    final ClientConfigProperties props = new ClientConfigProperties();
    props.setSendMessageTimeout(0);
    final HonoConnection connection = mockHonoConnection(vertx, props);
    when(connection.isConnected(anyLong())).thenReturn(Future.succeededFuture());
    sender = mockProtonSender();
    when(connection.createSender(anyString(), any(), any())).thenReturn(Future.succeededFuture(sender));
    tenantId = UUID.randomUUID().toString();
    tenantClient = mock(TenantClient.class);
    when(tenantClient.get(eq(tenantId), any())).thenReturn(Future.succeededFuture(TenantObject.from(tenantId)));
    commandTargetMapper = mock(CommandTargetMapper.class);
    final CommandRouterMetrics metrics = mock(CommandRouterMetrics.class);
    when(metrics.startTimer()).thenReturn(Timer.start());
    mappingAndDelegatingCommandHandler = new ProtonBasedMappingAndDelegatingCommandHandler(tenantClient, connection, commandTargetMapper, metrics);
}
Also used : Context(io.vertx.core.Context) CommandRouterMetrics(org.eclipse.hono.commandrouter.CommandRouterMetrics) CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) HonoConnection(org.eclipse.hono.client.HonoConnection) TenantClient(org.eclipse.hono.client.registry.TenantClient) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) EventBus(io.vertx.core.eventbus.EventBus) Vertx(io.vertx.core.Vertx) BeforeEach(org.junit.jupiter.api.BeforeEach)

Example 4 with CommandTargetMapper

use of org.eclipse.hono.commandrouter.CommandTargetMapper in project hono by eclipse.

the class Application method commandRouterService.

private CommandRouterService commandRouterService() {
    final DeviceRegistrationClient registrationClient = registrationClient();
    final TenantClient tenantClient = tenantClient();
    final CommandTargetMapper commandTargetMapper = CommandTargetMapper.create(registrationClient, deviceConnectionInfo, tracer);
    return new CommandRouterServiceImpl(amqpServerProperties, registrationClient, tenantClient, deviceConnectionInfo, commandConsumerFactoryProvider(tenantClient, commandTargetMapper), adapterInstanceStatusService, tracer);
}
Also used : CommandTargetMapper(org.eclipse.hono.commandrouter.CommandTargetMapper) ProtonBasedDeviceRegistrationClient(org.eclipse.hono.client.registry.amqp.ProtonBasedDeviceRegistrationClient) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) TenantClient(org.eclipse.hono.client.registry.TenantClient) ProtonBasedTenantClient(org.eclipse.hono.client.registry.amqp.ProtonBasedTenantClient) CommandRouterServiceImpl(org.eclipse.hono.commandrouter.impl.CommandRouterServiceImpl)

Example 5 with CommandTargetMapper

use of org.eclipse.hono.commandrouter.CommandTargetMapper 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)

Aggregations

TenantClient (org.eclipse.hono.client.registry.TenantClient)6 CommandTargetMapper (org.eclipse.hono.commandrouter.CommandTargetMapper)6 CommandRouterMetrics (org.eclipse.hono.commandrouter.CommandRouterMetrics)5 Tracer (io.opentracing.Tracer)4 Context (io.vertx.core.Context)4 Vertx (io.vertx.core.Vertx)4 BeforeEach (org.junit.jupiter.api.BeforeEach)4 Buffer (io.vertx.core.buffer.Buffer)3 JsonObject (io.vertx.core.json.JsonObject)3 VertxTestContext (io.vertx.junit5.VertxTestContext)3 CommandContext (org.eclipse.hono.client.command.CommandContext)3 KafkaBasedCommandContext (org.eclipse.hono.client.command.kafka.KafkaBasedCommandContext)3 KafkaBasedCommandResponseSender (org.eclipse.hono.client.command.kafka.KafkaBasedCommandResponseSender)3 KafkaBasedInternalCommandSender (org.eclipse.hono.client.command.kafka.KafkaBasedInternalCommandSender)3 Truth.assertThat (com.google.common.truth.Truth.assertThat)2 Timer (io.micrometer.core.instrument.Timer)2 CompositeFuture (io.vertx.core.CompositeFuture)2 Future (io.vertx.core.Future)2 Handler (io.vertx.core.Handler)2 Promise (io.vertx.core.Promise)2