如何转换Kafka Stream事件并仅在可以转换的情况下将其发送到另一个主题

时间:2019-07-10 11:14:00

标签: scala apache-kafka apache-kafka-streams

我想构建一个简单的Kafka流,尝试根据某些条件转换事件。如果事件可以转换,则转换后的事件将进入另一个主题。如果事件无法转换,则会再次存储在同一主题中,以供将来尝试。

假设我有这个:

case class Foo(a: String, b: String, c: Boolean)

def translate(value: String): Option[Foo] = {
  // ...
  // Returns an Option of Foo
}

所以我需要这样的东西:

val builder: StreamsBuilder = new StreamsBuilder()

builder
  .stream(topic)
  .map[String, String]((key, value) => translate(value))
  // If translate(value) is Some(value) send the value to a topic
  // Otherwise, send the original value (without being transformed) to the same topic

我完全被这个问题困扰。我遇到的最接近的事情是尝试使用一个布尔值创建一个结构,该结构告诉我事件是否可以转换,然后使用.branch创建不同的流。例如,如下所示:

def translate(value: String): (Boolean, Option[CPCTTMDataTransformed]) = {
  val eventTransformed = transform(value)
  eventTransformed match {
    case Some(value) => (true, Option(value))
    case None => (false, None)
  }
}

然后尝试执行以下操作:

builder
  .stream(topic)
  .map[String, (Boolean, Option[Foo])]((key, value) => translate(value))
  .branch(
    (_, element) => element._1,
  )
  .foreach {
    // Send the "true" to one topic and in the "false", send the original message to the original topic 
  }

但是,当然,我需要具有原始事件才能将其发送到主题。

尽管我已经了解了更复杂的结构,但最终我总是回到基于Some-None条件对流进行分支的问题。

1 个答案:

答案 0 :(得分:1)

也许使用Processor API。您有一个Processor负责翻译,如果翻译成功,则您context.forward(To.child("translated")),否则context.forward(To.child("retry"))

您将Topology手动插入到一起:

Topology topology = new Topology();
topology.addSource("source", topic);
topology.addProcessor("translator", () -> new TranslateProcessor(), "source");
topology.addSink("translated", resultTopic, "translator");
topology.addSink("retry", topic, "translator");