我遇到sink
(或中间flow
)实际上可以产生一些必须被推回(或追加)到Source
的副作用数据的情况。有没有办法使用流DSL实现这一目标?我可以使用一些阻塞队列或排序它来创建source
,然后将数据直接推送到该队列,但这会打破流的抽象。或许有一个我不了解的更好的解决方案?
答案 0 :(得分:4)
正如Viktor所说,你可以使用圆形图。
例如,partition
阶段允许您选择流的特定元素。
def partitionFunction(i: Int): Int = if (i % 2 == 0) 0 else 1
val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val in = Source(1 to 10)
val out = Sink.foreach[Int](println)
val addOne = Flow[Int].map(_ + 1)
val partition = builder.add(Partition[Int](2, partitionFunction))
val merge = builder.add(Merge[Int](2))
in ~> merge ~> partition
partition.out(0) ~> addOne ~> merge
partition.out(1) ~> out
ClosedShape
})
在此示例中,源in
连接到merge
的一个输入。整数然后通过partition
阶段,这将分开偶数和奇数。
偶数正在经过addOne
流程,然后进入merge
的第二个输入(这将再次让他们回到partition
阶段。)
奇数直接进入接收器out
。
这允许将一些值反馈回图表,但它很容易导致一个循环(这就是为什么addOne
阶段在这里很重要,没有它,偶数会被困在图)。
答案 1 :(得分:1)
Reactive-kafka做了类似的事情(至少在0.8版本中):它将Sink消耗的消息提交回源(Kafka消费者)。
KafkaCommitterSink是实施。它实际上并不是一个圆形的图形,而是它的更新和#39;据我所知,源代码独立于流程。