简体   繁体   English

你如何处理Akka Flow的期货?

[英]How do you deal with futures in Akka Flow?

I have built an akka graph that defines a flow. 我已经构建了一个定义流的akka​​图。 My objective is to reformat my future response and save it to a file. 我的目标是重新格式化我将来的响应并将其保存到文件中。 The flow can be outlined bellow: 流程可以概述如下:

val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
      import GraphDSL.Implicits._
      val balancer = builder.add(Balance[(HttpRequest, String)](6, waitForAllDownstreams = false))
      val merger = builder.add(Merge[Future[Map[String, String]]](6))
      val fileSink = FileIO.toPath(outputPath, options)
      val ignoreSink = Sink.ignore
      val in = Source(seeds)
      in ~> balancer.in
      for (i <- Range(0,6)) {
        balancer.out(i) ~>
          wikiFlow.async ~>
          // This maps to a Future[Map[String, String]]
          Flow[(Try[HttpResponse], String)].map(parseHtml) ~>
          merger
      }

      merger.out ~>
      // When we merge we need to map our Map to a file
      Flow[Future[Map[String, String]]].map((d) => {
        // What is the proper way of serializing future map
        // so I can work with it like a normal stream into fileSink?

        // I could manually do ->
        // d.foreach(someWriteToFileProcess(_))
        // with ignoreSink, but this defeats the nice
        // akka flow
      }) ~>
      fileSink

      ClosedShape
    })

I can hack this workflow to write my future map to a file via foreach, but I'm afraid this could somehow lead to concurrency issues with FileIO and it just doesn't feel right. 我可以破解这个工作流程,通过foreach将我未来的地图写入文件,但我担心这可能会导致FileIO的并发问题,而且感觉不对。 What is the proper way to handle futures with our akka flow? 使用我们的akka​​流程处理期货的正确方法是什么?

The easiest way to create a Flow which involves an asynchronous computation is by using mapAsync . 创建涉及异步计算的Flow的最简单方法是使用mapAsync

So... lets say you want to create a Flow which consumes Int and produces String using an asynchronous computation mapper: Int => Future[String] with a parallelism of 5. 所以......假设你想要创建一个使用异步计算mapper: Int => Future[String]消耗Int并生成StringFlow mapper: Int => Future[String] ,并行度为5。

val mapper: Int => Future[String] = (i: Int) => Future(i.toString)

val yourFlow = Flow[Int].mapAsync[String](5)(mapper)

Now, you can use this flow in your graph however you want. 现在,您可以根据需要在图表中使用此流程。

An example usage will be, 一个示例用法是,

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

  val intSource = Source(1 to 10)

  val printSink = Sink.foreach[String](s => println(s))

  val yourMapper: Int => Future[String] = (i: Int) => Future(i.toString)

  val yourFlow = Flow[Int].mapAsync[String](2)(yourMapper)

  intSource ~> yourFlow ~> printSink

  ClosedShape
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM