X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Fkafka%2Fwordcount%2Fquery%2FQueryStreamProcessor.java;h=3a1665fa9f6245c867e7703efdd957874e3d0343;hb=f929a47a66a2c14a291133aaa624ad9c5696bd53;hp=7dacd4b914e10717d539c69292300024e4b6c201;hpb=0648885ec026d7434561060dc7edb703efea6853;p=demos%2Fkafka%2Fwordcount diff --git a/src/main/java/de/juplo/kafka/wordcount/query/QueryStreamProcessor.java b/src/main/java/de/juplo/kafka/wordcount/query/QueryStreamProcessor.java index 7dacd4b..3a1665f 100644 --- a/src/main/java/de/juplo/kafka/wordcount/query/QueryStreamProcessor.java +++ b/src/main/java/de/juplo/kafka/wordcount/query/QueryStreamProcessor.java @@ -5,9 +5,7 @@ import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.streams.*; -import org.apache.kafka.streams.kstream.KStream; -import org.apache.kafka.streams.kstream.KTable; -import org.apache.kafka.streams.kstream.Materialized; +import org.apache.kafka.streams.kstream.*; import org.apache.kafka.streams.state.HostInfo; import org.apache.kafka.streams.state.KeyValueBytesStoreSupplier; import org.apache.kafka.streams.state.QueryableStoreTypes; @@ -22,7 +20,8 @@ import java.util.Properties; @Slf4j public class QueryStreamProcessor { - public static final String STORE_NAME = "rankings-by-username"; + public static final String USER_STORE_NAME = "users"; + public static final String RANKING_STORE_NAME = "rankings"; public final KafkaStreams streams; public final HostInfo hostInfo; @@ -34,37 +33,50 @@ public class QueryStreamProcessor HostInfo applicationServer, String usersInputTopic, String rankingInputTopic, - KeyValueBytesStoreSupplier storeSupplier) + KeyValueBytesStoreSupplier userStoreSupplier, + KeyValueBytesStoreSupplier rankingStoreSupplier) { Topology topology = buildTopology( usersInputTopic, rankingInputTopic, - storeSupplier); + userStoreSupplier, + rankingStoreSupplier); streams = new KafkaStreams(topology, props); hostInfo = applicationServer; - storeParameters = StoreQueryParameters.fromNameAndType(STORE_NAME, QueryableStoreTypes.keyValueStore());; + storeParameters = StoreQueryParameters.fromNameAndType(RANKING_STORE_NAME, QueryableStoreTypes.keyValueStore());; } static Topology buildTopology( String usersInputTopic, String rankingInputTopic, - KeyValueBytesStoreSupplier storeSupplier) + KeyValueBytesStoreSupplier userStoreSupplier, + KeyValueBytesStoreSupplier rankingStoreSupplier) { StreamsBuilder builder = new StreamsBuilder(); KTable users = builder - .stream(usersInputTopic) - .toTable(Materialized.with(null, new JsonSerde().copyWithType(User.class))); - KStream rankings = builder.stream(rankingInputTopic); + .stream( + usersInputTopic, + Consumed.with(Serdes.String(), new JsonSerde().copyWithType(User.class))) + .toTable( + Materialized + .as(userStoreSupplier) + .withKeySerde(Serdes.String()) + .withValueSerde(new JsonSerde().copyWithType(User.class))); + KStream rankings = builder + .stream(rankingInputTopic) + .map((key, value) -> new KeyValue<>(key.getUsername(), value)); rankings .join(users, (ranking, user) -> UserRanking.of( user.getFirstName(), user.getLastName(), - ranking.getEntries())) + ranking.getEntries()), + Joined.keySerde(Serdes.String())) .toTable( Materialized - .as(storeSupplier) + .as(rankingStoreSupplier) + .withKeySerde(Serdes.String()) .withValueSerde(new JsonSerde().copyWithType(UserRanking.class))); Topology topology = builder.build(); @@ -80,7 +92,7 @@ public class QueryStreamProcessor public Optional getRedirect(String username) { - KeyQueryMetadata metadata = streams.queryMetadataForKey(STORE_NAME, username, Serdes.String().serializer()); + KeyQueryMetadata metadata = streams.queryMetadataForKey(RANKING_STORE_NAME, username, Serdes.String().serializer()); HostInfo activeHost = metadata.activeHost(); log.debug("Local store for {}: {}, {}:{}", username, metadata.partition(), activeHost.host(), activeHost.port());