Поглотите источник с двумя приемниками и получите результат одного приемника - PullRequest
2 голосов
/ 09 июля 2019

Я бы хотел потреблять 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 Ответ

4 голосов
/ 09 июля 2019

Передайте в обоих приемниках метод построения графиков 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. Если вы хотите получить материализованное значение как addSink, так и subtractSink, используйте Keep.both:

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