Search in sources :

Example 1 with QuickTopicData

use of com.bakdata.quick.common.type.QuickTopicData in project quick by bakdata.

the class MutationFetcherTest method shouldIngestDataWithDifferentKeyTypes.

@ParameterizedTest(name = "shouldIngestDataWithDifferentKeyTypes ({0})")
@MethodSource("provideValueArgumentsForKeys")
<K, T> void shouldIngestDataWithDifferentKeyTypes(final TestParameterBuilder<K, String, T> testParameter) throws Exception {
    final String topic = testParameter.getTopic();
    final QuickData<T> keyInfo = testParameter.getInfoType();
    final QuickTopicData<T, String> info = new QuickTopicData<>(topic, TopicWriteType.MUTABLE, keyInfo, TestTypeUtils.newStringData());
    final KafkaConfig kafkaConfig = new KafkaConfig(kafkaCluster.getBrokerList(), schemaRegistry.getUrl());
    kafkaCluster.createTopic(TopicConfig.withName(topic).useDefaults());
    final TopicTypeService typeService = topicTypeService(keyInfo.getType(), QuickTopicType.STRING, null);
    final KafkaIngestService kafkaIngestService = new KafkaIngestService(typeService, kafkaConfig);
    final DataFetcher<String> mutationFetcher = new MutationFetcher<>(topic, "id", "name", new Lazy<>(() -> info), kafkaIngestService);
    final KeyValue<K, String> keyValue = testParameter.getKeyValue();
    final DataFetchingEnvironment env = DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(Map.of("id", keyValue.getKey(), "name", keyValue.getValue())).build();
    final String actual = mutationFetcher.get(env);
    assertThat(actual).isEqualTo(keyValue.getValue());
    final Optional<KeyValue<String, String>> consumedRecords = kafkaCluster.read(ReadKeyValues.from(topic, String.class).with(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyInfo.getSerde().deserializer().getClass()).with(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class)).stream().findFirst();
    assertThat(consumedRecords).isPresent().get().hasFieldOrPropertyWithValue("key", keyValue.getKey()).hasFieldOrPropertyWithValue("value", keyValue.getValue());
}
Also used : KafkaIngestService(com.bakdata.quick.gateway.ingest.KafkaIngestService) KeyValue(net.mguenther.kafka.junit.KeyValue) StringDeserializer(org.apache.kafka.common.serialization.StringDeserializer) QuickTopicData(com.bakdata.quick.common.type.QuickTopicData) DataFetchingEnvironment(graphql.schema.DataFetchingEnvironment) TopicTypeService(com.bakdata.quick.common.type.TopicTypeService) TestTopicTypeService(com.bakdata.quick.common.TestTopicTypeService) KafkaConfig(com.bakdata.quick.common.config.KafkaConfig) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 2 with QuickTopicData

use of com.bakdata.quick.common.type.QuickTopicData in project quick by bakdata.

the class MutationFetcherTest method shouldIngestDataWithDifferentValueTypes.

@ParameterizedTest(name = "shouldIngestDataWithDifferentValueTypes ({0})")
@MethodSource("provideValueArguments")
<V, T> void shouldIngestDataWithDifferentValueTypes(final TestParameterBuilder<String, V, T> testParameter) throws Exception {
    final String topic = testParameter.getTopic();
    final QuickData<T> valueInfo = testParameter.getInfoType();
    final QuickTopicData<String, T> info = new QuickTopicData<>(topic, TopicWriteType.MUTABLE, TestTypeUtils.newStringData(), valueInfo);
    final KafkaConfig kafkaConfig = new KafkaConfig(kafkaCluster.getBrokerList(), schemaRegistry.getUrl());
    kafkaCluster.createTopic(TopicConfig.withName(topic).useDefaults());
    final KafkaIngestService kafkaIngestService = new KafkaIngestService(topicTypeService(QuickTopicType.STRING, valueInfo.getType(), null), kafkaConfig);
    final DataFetcher<T> mutationFetcher = new MutationFetcher<>(topic, "id", "name", new Lazy<>(() -> info), kafkaIngestService);
    final KeyValue<String, V> keyValue = testParameter.getKeyValue();
    final DataFetchingEnvironment env = DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(Map.of("id", keyValue.getKey(), "name", keyValue.getValue())).build();
    final T actual = mutationFetcher.get(env);
    assertThat(actual).isEqualTo(keyValue.getValue());
    final Optional<KeyValue<String, T>> consumedRecords = kafkaCluster.read(ReadKeyValues.from(topic, testParameter.getClassType()).with("schema.registry.url", schemaRegistry.getUrl()).with(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, valueInfo.getSerde().deserializer().getClass())).stream().findFirst();
    assertThat(consumedRecords).isPresent().get().hasFieldOrPropertyWithValue("key", keyValue.getKey()).hasFieldOrPropertyWithValue("value", keyValue.getValue());
}
Also used : KafkaIngestService(com.bakdata.quick.gateway.ingest.KafkaIngestService) KeyValue(net.mguenther.kafka.junit.KeyValue) QuickTopicData(com.bakdata.quick.common.type.QuickTopicData) DataFetchingEnvironment(graphql.schema.DataFetchingEnvironment) KafkaConfig(com.bakdata.quick.common.config.KafkaConfig) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 3 with QuickTopicData

use of com.bakdata.quick.common.type.QuickTopicData in project quick by bakdata.

the class IngestController method convertIngestData.

/**
 * Processes raw input data for ingesting.
 *
 * <p>
 * Two steps are necessary to ingest the raw payload:
 * <ul>
 *    <li> parse it
 *    <li> check for existing keys if the topic is immutable
 * </ul>
 *
 * <p>
 * This method handles both steps and then forwards all non-existing {@link KeyValuePair} to the
 * {@link IngestService}.
 * Further, it handles merging the error messages. The method returns an error for existing keys as well as possible
 * errors in the ingest service.
 *
 * @param topic   the topic to ingest to
 * @param payload the raw payload
 * @param data    the topic information for the topic
 * @param <K>     the key type of the topic
 * @param <V>     the value type of the topic
 * @return merged completable possibly containing errors from existing keys or the ingest service
 */
private <K, V> Completable convertIngestData(final String topic, final String payload, final QuickTopicData<K, V> data) {
    final Single<List<KeyValuePair<K, V>>> list = Single.fromCallable(() -> this.parser.parseInputData(payload, data));
    return list.flatMap(pairs -> this.filter.prepareIngest(data, pairs)).flatMapCompletable(pairs -> {
        final Completable existingError = createErrorsForExistingKeys(topic, pairs);
        final Completable ingest = this.ingestService.sendData(topic, pairs.getDataToIngest());
        return Completable.mergeArrayDelayError(existingError, ingest);
    });
}
Also used : Controller(io.micronaut.http.annotation.Controller) Secured(io.micronaut.security.annotation.Secured) TopicTypeService(com.bakdata.quick.common.type.TopicTypeService) QuickTopicData(com.bakdata.quick.common.type.QuickTopicData) Completable(io.reactivex.Completable) IngestFilter(com.bakdata.quick.ingest.service.IngestFilter) Delete(io.micronaut.http.annotation.Delete) SecurityRule(io.micronaut.security.rules.SecurityRule) BadArgumentException(com.bakdata.quick.common.exception.BadArgumentException) Single(io.reactivex.Single) Collectors(java.util.stream.Collectors) Post(io.micronaut.http.annotation.Post) Inject(javax.inject.Inject) IngestParser(com.bakdata.quick.ingest.service.IngestParser) IngestService(com.bakdata.quick.ingest.service.IngestService) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) Body(io.micronaut.http.annotation.Body) KeyValuePair(com.bakdata.quick.common.api.model.KeyValuePair) IngestLists(com.bakdata.quick.ingest.service.IngestFilter.IngestLists) Completable(io.reactivex.Completable) List(java.util.List)

Example 4 with QuickTopicData

use of com.bakdata.quick.common.type.QuickTopicData in project quick by bakdata.

the class SubscriptionFetcherTest method shouldFetchValues.

@ParameterizedTest(name = "shouldFetchValues ({0})")
@MethodSource("provideValueArguments")
<V> void shouldFetchValues(final String topic, final List<KeyValue<String, V>> keyValues, final QuickData<V> valueInfo, final List<V> expected) throws InterruptedException {
    final QuickTopicData<String, V> info = new QuickTopicData<>(topic, TopicWriteType.IMMUTABLE, TestTypeUtils.newStringData(), valueInfo);
    final KafkaConfig kafkaConfig = new KafkaConfig(kafkaCluster.getBrokerList(), "http://no");
    kafkaCluster.createTopic(TopicConfig.withName(topic).useDefaults());
    final SendKeyValuesTransactional<String, V> sendRequest = SendKeyValuesTransactional.inTransaction(topic, keyValues).with(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class).with(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, valueInfo.getSerde().serializer().getClass()).build();
    kafkaCluster.send(sendRequest);
    final SubscriptionFetcher<String, V> subscriptionFetcher = new SubscriptionFetcher<>(kafkaConfig, new Lazy<>(() -> info), "test-query", OffsetStrategy.EARLIEST, null);
    final Publisher<V> publisher = subscriptionFetcher.get(DataFetchingEnvironmentImpl.newDataFetchingEnvironment().build());
    final TestSubscriber<V> testSubscriber = TestSubscriber.create();
    // ensures that multiple subscriber work
    final TestSubscriber<V> test2Subscriber = TestSubscriber.create();
    publisher.subscribe(testSubscriber);
    publisher.subscribe(test2Subscriber);
    await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> {
        assertThat(testSubscriber.values()).containsExactlyElementsOf(expected);
        assertThat(test2Subscriber.values()).containsExactlyElementsOf(expected);
    });
}
Also used : QuickTopicData(com.bakdata.quick.common.type.QuickTopicData) KafkaConfig(com.bakdata.quick.common.config.KafkaConfig) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 5 with QuickTopicData

use of com.bakdata.quick.common.type.QuickTopicData in project quick by bakdata.

the class MirrorTopologyTest method createTopology.

static Topology createTopology(final Properties properties) {
    final String topic = INPUT_TOPICS.get(0);
    final QuickTopicData<Integer, Integer> data = new QuickTopicData<>(topic, TopicWriteType.MUTABLE, newIntegerData(), newIntegerData());
    data.getKeyData().getSerde().configure(Maps.fromProperties(properties), true);
    data.getValueData().getSerde().configure(Maps.fromProperties(properties), false);
    final QuickTopologyData<Integer, Integer> topologyInfo = QuickTopologyData.<Integer, Integer>builder().inputTopics(INPUT_TOPICS).topicData(data).build();
    final MirrorTopology<Integer, Integer> mirrorTopology = MirrorTopology.<Integer, Integer>builder().topologyData(topologyInfo).storeName(STORE_NAME).retentionStoreName(RETENTION_STORE_NAME).storeType(StoreType.INMEMORY).build();
    final StreamsBuilder builder = new StreamsBuilder();
    return mirrorTopology.createTopology(builder);
}
Also used : StreamsBuilder(org.apache.kafka.streams.StreamsBuilder) QuickTopicData(com.bakdata.quick.common.type.QuickTopicData)

Aggregations

QuickTopicData (com.bakdata.quick.common.type.QuickTopicData)9 KafkaConfig (com.bakdata.quick.common.config.KafkaConfig)4 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)4 MethodSource (org.junit.jupiter.params.provider.MethodSource)4 DataFetchingEnvironment (graphql.schema.DataFetchingEnvironment)3 TopicTypeService (com.bakdata.quick.common.type.TopicTypeService)2 KafkaIngestService (com.bakdata.quick.gateway.ingest.KafkaIngestService)2 Completable (io.reactivex.Completable)2 KeyValue (net.mguenther.kafka.junit.KeyValue)2 ChartRecord (com.bakdata.quick.avro.ChartRecord)1 TestTopicTypeService (com.bakdata.quick.common.TestTopicTypeService)1 KeyValuePair (com.bakdata.quick.common.api.model.KeyValuePair)1 BadArgumentException (com.bakdata.quick.common.exception.BadArgumentException)1 QuickData (com.bakdata.quick.common.type.QuickTopicData.QuickData)1 QuickTopicType (com.bakdata.quick.common.type.QuickTopicType)1 IngestFilter (com.bakdata.quick.ingest.service.IngestFilter)1 IngestLists (com.bakdata.quick.ingest.service.IngestFilter.IngestLists)1 IngestParser (com.bakdata.quick.ingest.service.IngestParser)1 IngestService (com.bakdata.quick.ingest.service.IngestService)1 Body (io.micronaut.http.annotation.Body)1