[英]Akka-streams mapConcat not working with cycled RunnableGraph
I have RunnableGraph
like following. 我有如下的
RunnableGraph
。 When there is simple map
between broadcast
and merge
stages everything is fine. 当
broadcast
和merge
阶段之间有简单的map
,一切都很好。 However, when it comes to mapConcat
, this code is not working after consuming the first element. 但是,当涉及
mapConcat
,使用第一个元素后此代码将无法正常工作。
I want to know why it doesn't work. 我想知道为什么它不起作用。
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
import GraphDSL.Implicits._
val M = b.add(MergePreferred[Int](1))
val B = b.add(Broadcast[Int](2))
val S = Source(List(3))
S ~> M ~> Flow[Int].map { s => println(s); s } ~> B ~> Sink.ignore
M.preferred <~ Flow[Int].map(x => List.fill(3)(x-1)).mapConcat(x => {println(x); x}).filter(_ > 0) <~ B
ClosedShape
})
// run() output:
// 3
// List(2,2,2)
The mapConcat
stage blocks the feedback loop, and that is expected. mapConcat
阶段阻止了反馈循环,这是预期的。 Consider the following chain of events: 考虑以下事件链:
mapConcat
function prints List(2,2,2)
mapConcat
函数打印List(2,2,2)
mapConcat
stage needs demand to emit the first of the 3 available elements (2, 2, 2) mapConcat
阶段需要发出3个可用元素( mapConcat
的第一个的需求 Sink.ignore
(that never backpressures), and the mapConcat
itself. Sink.ignore
(永不背压)和mapConcat
本身。 mapConcat
backpressures if "there are still remaining elements from the previously calculated collection", as per the docs . mapConcat
背压,如果“是否仍有从先前计算的收集要素”,按照该文档 。 This is indeed the case. In other words, your cycle is unbalanced. 换句话说,您的周期是不平衡的。 You are introducing more elements in the feedback loop than you are removing.
您在反馈循环中引入的元素要多于要删除的元素。
This issue is explained in detail in this documentation page , where a couple of solutions are also presented. 在本文档页面中详细解释了此问题,其中还提供了一些解决方案。 For your specific case, because of the filter stage you have, introducing a buffer larger than 13 would print all the elements.
对于您的特定情况,由于您具有过滤器阶段,因此引入大于13的缓冲区将打印所有元素。 However, note that the graph will just hang and not complete afterwards.
但是,请注意,该图形将只是挂起,并且此后不会完成。
S ~> M ~> Flow[Int].map { s => println(s); s } ~> B ~> Sink.ignore
M.preferred <~ Flow[Int].buffer(20, OverflowStrategy.dropHead) <~ Flow[Int].map(x => List.fill(3)(x-1)).mapConcat(x => {println(x); x}).filter(_ > 0) <~ B
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.