[英]Akka streams - resuming graph with broadcast and zip after failure
I have a flow graph with broadcast and zip inside. 我有一个内置广播和拉链的流程图。 If something (regardless what is it) fails inside this flow, I'd like to drop the problematic element passed to it and resume.
如果某个东西(无论它是什么)在这个流程中失败了,我想删除传递给它的有问题的元素并恢复。 I came up with the following solution:
我提出了以下解决方案:
val flow = Flow.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val dangerousFlow = Flow[Int].map {
case 5 => throw new RuntimeException("BOOM!")
case x => x
}
val safeFlow = Flow[Int]
val bcast = builder.add(Broadcast[Int](2))
val zip = builder.add(Zip[Int, Int])
bcast ~> dangerousFlow ~> zip.in0
bcast ~> safeFlow ~> zip.in1
FlowShape(bcast.in, zip.out)
})
Source(1 to 9)
.via(flow)
.withAttributes(ActorAttributes.supervisionStrategy(Supervision.restartingDecider))
.runWith(Sink.foreach(println))
I'd expect it to print: 我希望它能打印出来:
(1,1)
(2,2)
(3,3)
(4,4)
(5,5)
(6,6)
(7,7)
(8,8)
(9,9)
However, it deadlocks, printing only: 但是,它只会出现死锁,只能打印:
(1,1)
(2,2)
(3,3)
(4,4)
We've done some debugging, and it turns out it applied the "resume" strategy to its children, which caused dangerousFlow
to resume after failure and thus to demand an element from bcast
. 我们已经做了一些调试,结果发现它将“恢复”策略应用于其子
bcast
,这导致dangerousFlow
的流程在失败后恢复,从而要求bcast
的元素。 bcast
won't emit an element until safeFlow
demands another element, which actually never happens (because it's waiting for demand from zip
). bcast
不会发出一个元素,直到safeFlow
要求另一个元素,实际上从未发生(因为它正在等待来自zip
需求)。
Is there a way to resume the graph regardless of what went wrong inside one of the stages? 有没有办法恢复图表,无论其中一个阶段内出了什么问题?
I think you understood the problem well. 我认为你很好地理解了这个问题。 You saw that, when your element
5
crashes dangerousFlow
, you should also stop the element 5
that is going through safeFlow
because if it reaches the zip
stage, you have the problem you describe. 您看到,当您的元素
5
崩溃dangerousFlow
,您还应该停止正在通过safeFlow
的元素5
,因为如果它到达zip
阶段,则会出现您描述的问题。 I don't know how to solve your problem between the broadcast
and zip
stages, but what about pushing the problem further, where it is easier to handle? 我不知道如何在
broadcast
和zip
阶段之间解决你的问题,但是如何进一步推动问题,哪里更容易处理?
Consider using the following dangerousFlow
: 考虑使用以下
dangerousFlow
:
import scala.util._
val dangerousFlow = Flow[Int].map {
case 5 => Failure(new RuntimeException("BOOM!"))
case x => Success(x)
}
Even in case of problem, dangerousFlow
would still emit data. 即使出现问题,
dangerousFlow
仍会发出数据。 You can then zip
as you are currently doing and would just need to add a collect
stage as last step of your graph. 然后,您可以按照当前的方式进行
zip
,只需添加一个collect
阶段作为图表的最后一步。 On a flow, this would look like: 在流程上,这看起来像:
Flow[(Try[Int], Int)].collect {
case (Success(s), i) => s -> i
}
Now if, as you wrote, you really expect it to output the (5, 5)
tuple, use the following: 现在,如果你正如你所写,你真的希望它输出
(5, 5)
元组,请使用以下内容:
Flow[(Try[Int], Int)].collect {
case (Success(s), i) => s -> i
case (_, i) => i -> i
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.