保持与akka流中的上游元素的关系

时间:2017-10-25 05:56:31

标签: scala akka akka-stream

我有以下代码示例,工作正常。我想添加一些更改来保持请求和响应之间的关系。我怎么能这样啊? Rest api flow的具体化值为NotUsed。有可能以某种方式使用Keep.both吗?

// this flow is provided by some third party library that I can't change in place
val someRestApiFlow: Flow[Int, Int, NotUsed] = Flow[Int].mapAsync(10)(x => Future(x + 1))

val digits: Source[Int, NotUsed] = Source(List(1, 2, 3))

val r = digits.via(someRestApiFlow).runForeach(println)

结果是

2
3
4

我希望结果像

1 -> 2
2 -> 3
3 -> 4

2 个答案:

答案 0 :(得分:1)

我也遇到过几次这种情况。我找到的唯一解决方案是使用DSL创建图表并使用broadcastzip阶段。

import akka.actor.ActorSystem
import akka.stream.scaladsl.{Broadcast, Flow, GraphDSL, RunnableGraph, Sink, Source, Zip}
import akka.stream.{ActorMaterializer, ClosedShape}
import akka.{Done, NotUsed}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object Main extends App {

  implicit val system: ActorSystem = ActorSystem("my-system")
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  val graph = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
    import GraphDSL.Implicits._
    val src: Source[Int, NotUsed] = Source(List(1, 2, 3))
    val someRestApiFlow: Flow[Int, Int, NotUsed] = Flow[Int].mapAsync(10)(x => Future(x + 1))
    val out: Sink[(Int, Int), Future[Done]] = Sink.foreach[(Int, Int)](println)

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


    src ~> bcast ~>                    zip.in0
           bcast ~> someRestApiFlow ~> zip.in1
                                       zip.out ~> out

    ClosedShape
  })

  graph.run()

}

这里正在做的是我们正在广播zip和自定义流的输入,并且该zip还等待自定义流的结果,最后将它们合并到发送接收器。

答案 1 :(得分:1)

您可以使用广播元素创建2个单独的流。广播的第一个输出通过someRestApiFlow,广播的第二个输出未经修改。然后使用广播流的第二个输出将someRestApiFlow的输出压缩。这样做,你有输入元素和通过someRestApiFlow转换的结果。

digits ---> broadcast --> someRestApiFlow ---> zip --> result
                     \----------------------/