消耗具有两个接收器的源并获得一个接收器的结果

时间:2019-07-09 15:06:21

标签: scala akka akka-stream

我想使用两个不同的接收器来使用Source

简化示例:

val source = Source(1 to 20)

val addSink = Sink.fold[Int, Int](0)(_ + _)
val subtractSink = Sink.fold[Int, Int](0)(_ - _)

val graph = GraphDSL.create() { implicit builder =>
  import GraphDSL.Implicits._

  val bcast = builder.add(Broadcast[Int](2))

  source ~> bcast.in

  bcast.out(0) ~> addSink
  bcast.out(1) ~> subtrackSink

  ClosedShape
}

RunnableGraph.fromGraph(graph).run()

val result: Future[Int] = ???

我需要能够检索addSink的结果。 RunnableGraph.fromGraph(graph).run()给了我NotUsed, 但我想得到Int(第一折Sink的结果)。有可能吗?

1 个答案:

答案 0 :(得分:4)

将两个接收器都传递到图形构建器的create方法,该方法使您可以访问它们各自的物化值:

val graph = GraphDSL.create(addSink, subtractSink)((_, _)) { implicit builder =>
  (aSink, sSink) =>
  import GraphDSL.Implicits._

  val bcast = builder.add(Broadcast[Int](2))

  source ~> bcast.in
  bcast.out(0) ~> aSink
  bcast.out(1) ~> sSink
  ClosedShape
}

val (addResult, subtractResult): (Future[Int], Future[Int]) =
  RunnableGraph.fromGraph(graph).run() 

或者,您可以放弃图表DSL并使用alsoToMat

val result: Future[Int] =
  Source(1 to 20)
    .alsoToMat(addSink)(Keep.right)
    .toMat(subtractSink)(Keep.left)
    .run()

以上内容为您提供了addSink的物化值。如果要同时获得addSinksubtractSink的物化值,请使用Keep.both

val (addResult, subtractResult): (Future[Int], Future[Int]) =
  Source(1 to 20)
    .alsoToMat(addSink)(Keep.right)
    .toMat(subtractSink)(Keep.both) // <--
    .run()