我已经构建了一个定义流的akka图。我的目标是重新格式化我将来的响应并将其保存到文件中。流程可以概述如下:
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
})
我可以破解这个工作流程,通过foreach将我的未来地图写入文件,但我担心这可能会以某种方式导致FileIO的并发问题,而且感觉不对。使用我们的akka流程处理期货的正确方法是什么?
答案 0 :(得分:20)
创建涉及异步计算的Flow
的最简单方法是使用mapAsync
。
所以...让我们假设你要创建一个消耗Flow
的{{1}}并使用并行度为5的异步计算Int
生成String
。
mapper: Int => Future[String]
现在,您可以根据需要在图表中使用此流程。
示例用法是,
val mapper: Int => Future[String] = (i: Int) => Future(i.toString)
val yourFlow = Flow[Int].mapAsync[String](5)(mapper)