|
|
|
@ -19,9 +19,11 @@ package org.apache.kafka.streams.kstream.internals;
@@ -19,9 +19,11 @@ package org.apache.kafka.streams.kstream.internals;
|
|
|
|
|
import org.apache.kafka.common.serialization.IntegerSerializer; |
|
|
|
|
import org.apache.kafka.common.serialization.Serdes; |
|
|
|
|
import org.apache.kafka.common.serialization.StringSerializer; |
|
|
|
|
import org.apache.kafka.streams.KeyValue; |
|
|
|
|
import org.apache.kafka.streams.KeyValueTimestamp; |
|
|
|
|
import org.apache.kafka.streams.StreamsBuilder; |
|
|
|
|
import org.apache.kafka.streams.StreamsConfig; |
|
|
|
|
import org.apache.kafka.streams.Topology; |
|
|
|
|
import org.apache.kafka.streams.TopologyTestDriver; |
|
|
|
|
import org.apache.kafka.streams.TopologyWrapper; |
|
|
|
|
import org.apache.kafka.streams.errors.StreamsException; |
|
|
|
@ -77,6 +79,38 @@ public class KStreamKStreamJoinTest {
@@ -77,6 +79,38 @@ public class KStreamKStreamJoinTest {
|
|
|
|
|
shouldLogAndMeterOnSkippedRecordsWithNullValue(StreamsConfig.METRICS_LATEST); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void shouldReuseRepartitionTopicWithGeneratedName() { |
|
|
|
|
final StreamsBuilder builder = new StreamsBuilder(); |
|
|
|
|
final Properties props = new Properties(); |
|
|
|
|
props.put(StreamsConfig.TOPOLOGY_OPTIMIZATION, StreamsConfig.NO_OPTIMIZATION); |
|
|
|
|
final KStream<String, String> stream1 = builder.stream("topic", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> stream2 = builder.stream("topic2", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> stream3 = builder.stream("topic3", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> newStream = stream1.map((k, v) -> new KeyValue<>(v, k)); |
|
|
|
|
newStream.join(stream2, (value1, value2) -> value1 + value2, JoinWindows.of(ofMillis(100))).to("out-one"); |
|
|
|
|
newStream.join(stream3, (value1, value2) -> value1 + value2, JoinWindows.of(ofMillis(100))).to("out-to"); |
|
|
|
|
assertEquals(expectedTopologyWithGeneratedRepartitionTopic, builder.build(props).describe().toString()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void shouldCreateRepartitionTopicsWithUserProvidedName() { |
|
|
|
|
final StreamsBuilder builder = new StreamsBuilder(); |
|
|
|
|
final Properties props = new Properties(); |
|
|
|
|
props.put(StreamsConfig.TOPOLOGY_OPTIMIZATION, StreamsConfig.NO_OPTIMIZATION); |
|
|
|
|
final KStream<String, String> stream1 = builder.stream("topic", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> stream2 = builder.stream("topic2", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> stream3 = builder.stream("topic3", Consumed.with(Serdes.String(), Serdes.String())); |
|
|
|
|
final KStream<String, String> newStream = stream1.map((k, v) -> new KeyValue<>(v, k)); |
|
|
|
|
final StreamJoined<String, String, String> streamJoined = StreamJoined.with(Serdes.String(), Serdes.String(), Serdes.String()); |
|
|
|
|
newStream.join(stream2, (value1, value2) -> value1 + value2, JoinWindows.of(ofMillis(100)), streamJoined.withName("first-join")).to("out-one"); |
|
|
|
|
newStream.join(stream3, (value1, value2) -> value1 + value2, JoinWindows.of(ofMillis(100)), streamJoined.withName("second-join")).to("out-two"); |
|
|
|
|
final Topology topology = builder.build(props); |
|
|
|
|
System.out.println(topology.describe().toString()); |
|
|
|
|
assertEquals(expectedTopologyWithUserNamedRepartitionTopics, topology.describe().toString()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void shouldLogAndMeterOnSkippedRecordsWithNullValue(final String builtInMetricsVersion) { |
|
|
|
|
final StreamsBuilder builder = new StreamsBuilder(); |
|
|
|
|
|
|
|
|
@ -1556,4 +1590,122 @@ public class KStreamKStreamJoinTest {
@@ -1556,4 +1590,122 @@ public class KStreamKStreamJoinTest {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final String expectedTopologyWithUserNamedRepartitionTopics = "Topologies:\n" + |
|
|
|
|
" Sub-topology: 0\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000000 (topics: [topic])\n" + |
|
|
|
|
" --> KSTREAM-MAP-0000000003\n" + |
|
|
|
|
" Processor: KSTREAM-MAP-0000000003 (stores: [])\n" + |
|
|
|
|
" --> second-join-left-repartition-filter, first-join-left-repartition-filter\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000000\n" + |
|
|
|
|
" Processor: first-join-left-repartition-filter (stores: [])\n" + |
|
|
|
|
" --> first-join-left-repartition-sink\n" + |
|
|
|
|
" <-- KSTREAM-MAP-0000000003\n" + |
|
|
|
|
" Processor: second-join-left-repartition-filter (stores: [])\n" + |
|
|
|
|
" --> second-join-left-repartition-sink\n" + |
|
|
|
|
" <-- KSTREAM-MAP-0000000003\n" + |
|
|
|
|
" Sink: first-join-left-repartition-sink (topic: first-join-left-repartition)\n" + |
|
|
|
|
" <-- first-join-left-repartition-filter\n" + |
|
|
|
|
" Sink: second-join-left-repartition-sink (topic: second-join-left-repartition)\n" + |
|
|
|
|
" <-- second-join-left-repartition-filter\n" + |
|
|
|
|
"\n" + |
|
|
|
|
" Sub-topology: 1\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000001 (topics: [topic2])\n" + |
|
|
|
|
" --> first-join-other-windowed\n" + |
|
|
|
|
" Source: first-join-left-repartition-source (topics: [first-join-left-repartition])\n" + |
|
|
|
|
" --> first-join-this-windowed\n" + |
|
|
|
|
" Processor: first-join-other-windowed (stores: [KSTREAM-JOINOTHER-0000000010-store])\n" + |
|
|
|
|
" --> first-join-other-join\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000001\n" + |
|
|
|
|
" Processor: first-join-this-windowed (stores: [KSTREAM-JOINTHIS-0000000009-store])\n" + |
|
|
|
|
" --> first-join-this-join\n" + |
|
|
|
|
" <-- first-join-left-repartition-source\n" + |
|
|
|
|
" Processor: first-join-other-join (stores: [KSTREAM-JOINTHIS-0000000009-store])\n" + |
|
|
|
|
" --> first-join-merge\n" + |
|
|
|
|
" <-- first-join-other-windowed\n" + |
|
|
|
|
" Processor: first-join-this-join (stores: [KSTREAM-JOINOTHER-0000000010-store])\n" + |
|
|
|
|
" --> first-join-merge\n" + |
|
|
|
|
" <-- first-join-this-windowed\n" + |
|
|
|
|
" Processor: first-join-merge (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-SINK-0000000012\n" + |
|
|
|
|
" <-- first-join-this-join, first-join-other-join\n" + |
|
|
|
|
" Sink: KSTREAM-SINK-0000000012 (topic: out-one)\n" + |
|
|
|
|
" <-- first-join-merge\n" + |
|
|
|
|
"\n" + |
|
|
|
|
" Sub-topology: 2\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000002 (topics: [topic3])\n" + |
|
|
|
|
" --> second-join-other-windowed\n" + |
|
|
|
|
" Source: second-join-left-repartition-source (topics: [second-join-left-repartition])\n" + |
|
|
|
|
" --> second-join-this-windowed\n" + |
|
|
|
|
" Processor: second-join-other-windowed (stores: [KSTREAM-JOINOTHER-0000000019-store])\n" + |
|
|
|
|
" --> second-join-other-join\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000002\n" + |
|
|
|
|
" Processor: second-join-this-windowed (stores: [KSTREAM-JOINTHIS-0000000018-store])\n" + |
|
|
|
|
" --> second-join-this-join\n" + |
|
|
|
|
" <-- second-join-left-repartition-source\n" + |
|
|
|
|
" Processor: second-join-other-join (stores: [KSTREAM-JOINTHIS-0000000018-store])\n" + |
|
|
|
|
" --> second-join-merge\n" + |
|
|
|
|
" <-- second-join-other-windowed\n" + |
|
|
|
|
" Processor: second-join-this-join (stores: [KSTREAM-JOINOTHER-0000000019-store])\n" + |
|
|
|
|
" --> second-join-merge\n" + |
|
|
|
|
" <-- second-join-this-windowed\n" + |
|
|
|
|
" Processor: second-join-merge (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-SINK-0000000021\n" + |
|
|
|
|
" <-- second-join-this-join, second-join-other-join\n" + |
|
|
|
|
" Sink: KSTREAM-SINK-0000000021 (topic: out-two)\n" + |
|
|
|
|
" <-- second-join-merge\n\n"; |
|
|
|
|
|
|
|
|
|
private final String expectedTopologyWithGeneratedRepartitionTopic = "Topologies:\n" + |
|
|
|
|
" Sub-topology: 0\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000000 (topics: [topic])\n" + |
|
|
|
|
" --> KSTREAM-MAP-0000000003\n" + |
|
|
|
|
" Processor: KSTREAM-MAP-0000000003 (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-FILTER-0000000005\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000000\n" + |
|
|
|
|
" Processor: KSTREAM-FILTER-0000000005 (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-SINK-0000000004\n" + |
|
|
|
|
" <-- KSTREAM-MAP-0000000003\n" + |
|
|
|
|
" Sink: KSTREAM-SINK-0000000004 (topic: KSTREAM-MAP-0000000003-repartition)\n" + |
|
|
|
|
" <-- KSTREAM-FILTER-0000000005\n" + |
|
|
|
|
"\n" + |
|
|
|
|
" Sub-topology: 1\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000006 (topics: [KSTREAM-MAP-0000000003-repartition])\n" + |
|
|
|
|
" --> KSTREAM-WINDOWED-0000000007, KSTREAM-WINDOWED-0000000016\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000001 (topics: [topic2])\n" + |
|
|
|
|
" --> KSTREAM-WINDOWED-0000000008\n" + |
|
|
|
|
" Source: KSTREAM-SOURCE-0000000002 (topics: [topic3])\n" + |
|
|
|
|
" --> KSTREAM-WINDOWED-0000000017\n" + |
|
|
|
|
" Processor: KSTREAM-WINDOWED-0000000007 (stores: [KSTREAM-JOINTHIS-0000000009-store])\n" + |
|
|
|
|
" --> KSTREAM-JOINTHIS-0000000009\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000006\n" + |
|
|
|
|
" Processor: KSTREAM-WINDOWED-0000000008 (stores: [KSTREAM-JOINOTHER-0000000010-store])\n" + |
|
|
|
|
" --> KSTREAM-JOINOTHER-0000000010\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000001\n" + |
|
|
|
|
" Processor: KSTREAM-WINDOWED-0000000016 (stores: [KSTREAM-JOINTHIS-0000000018-store])\n" + |
|
|
|
|
" --> KSTREAM-JOINTHIS-0000000018\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000006\n" + |
|
|
|
|
" Processor: KSTREAM-WINDOWED-0000000017 (stores: [KSTREAM-JOINOTHER-0000000019-store])\n" + |
|
|
|
|
" --> KSTREAM-JOINOTHER-0000000019\n" + |
|
|
|
|
" <-- KSTREAM-SOURCE-0000000002\n" + |
|
|
|
|
" Processor: KSTREAM-JOINOTHER-0000000010 (stores: [KSTREAM-JOINTHIS-0000000009-store])\n" + |
|
|
|
|
" --> KSTREAM-MERGE-0000000011\n" + |
|
|
|
|
" <-- KSTREAM-WINDOWED-0000000008\n" + |
|
|
|
|
" Processor: KSTREAM-JOINOTHER-0000000019 (stores: [KSTREAM-JOINTHIS-0000000018-store])\n" + |
|
|
|
|
" --> KSTREAM-MERGE-0000000020\n" + |
|
|
|
|
" <-- KSTREAM-WINDOWED-0000000017\n" + |
|
|
|
|
" Processor: KSTREAM-JOINTHIS-0000000009 (stores: [KSTREAM-JOINOTHER-0000000010-store])\n" + |
|
|
|
|
" --> KSTREAM-MERGE-0000000011\n" + |
|
|
|
|
" <-- KSTREAM-WINDOWED-0000000007\n" + |
|
|
|
|
" Processor: KSTREAM-JOINTHIS-0000000018 (stores: [KSTREAM-JOINOTHER-0000000019-store])\n" + |
|
|
|
|
" --> KSTREAM-MERGE-0000000020\n" + |
|
|
|
|
" <-- KSTREAM-WINDOWED-0000000016\n" + |
|
|
|
|
" Processor: KSTREAM-MERGE-0000000011 (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-SINK-0000000012\n" + |
|
|
|
|
" <-- KSTREAM-JOINTHIS-0000000009, KSTREAM-JOINOTHER-0000000010\n" + |
|
|
|
|
" Processor: KSTREAM-MERGE-0000000020 (stores: [])\n" + |
|
|
|
|
" --> KSTREAM-SINK-0000000021\n" + |
|
|
|
|
" <-- KSTREAM-JOINTHIS-0000000018, KSTREAM-JOINOTHER-0000000019\n" + |
|
|
|
|
" Sink: KSTREAM-SINK-0000000012 (topic: out-one)\n" + |
|
|
|
|
" <-- KSTREAM-MERGE-0000000011\n" + |
|
|
|
|
" Sink: KSTREAM-SINK-0000000021 (topic: out-to)\n" + |
|
|
|
|
" <-- KSTREAM-MERGE-0000000020\n\n"; |
|
|
|
|
} |