用DSL KStream向KTable转换的Kafka墓碑

时间:2020-03-06 14:12:01

标签: java kotlin apache-kafka-streams

我有一个KStream<String, X>,我实际上想将其转换为KTable<String, Y>

我能找到的使用DSL来实现此目标的唯一方法是使用map,group然后reduce。

val stream: KStream<String, X> = ...
val table: KTable<String, Y> = stream
  .mapValues({ value -> toYOrNull(value)})
  .groupByKey(Grouped.with(Serdes.String(), ySerde))
  .reduce(
    {old: Y?, updated: Y? -> updated},
    Materialized.`as`<String, Y, KeyValueStore<Bytes, ByteArray>>("y-store")
      .withKeySerde(Serdes.String()
      .withValueSerde(ySerde)
  )

我希望当updatedreduce的值为null时能处理这种情况,但是当我使用TopologyTestDriver检查商店时,似乎仍然可以有旧版本。我在做什么错了?

这是我的测试

@Test
fun shouldDeleteFromTableWhenNull() {
  val store = testDriver.getKeyValueStore<String, Y?>("y-store")
  store.put("key", Y())

  inputTopic.pipeInput("key", anXThatMapsToANullY)

  assertThat(store.get("key")).isNull() // Fails as the old entry is still there
}

2 个答案:

答案 0 :(得分:1)

值为空的记录将被忽略。

根据文档KGroupedStream::reduce(...) Java Doc

,这是预期的行为

通过分组键组合此流中的记录值。空键为或值的记录将被忽略

答案 1 :(得分:1)

在即将发布的Apache Kafka 2.5版本中,添加了一个新的运算符KStream#toTable()来解决此用例(参见https://issues.apache.org/jira/browse/KAFKA-7658

在较早的版本中,您将需要使用非空的“代理删除值”,以避免记录被删除,并且如果其看到“代理删除值”,则让reduce函数返回null。 / p>

相关问题