我正在尝试为包含并行处理流程的Akka流定义一个图形(我使用的是Akka.NET,但这不重要)。想象一下订单的数据源,每个订单都包含订单ID和产品列表(订单商品)。工作流程如下:
步骤1(Source.From),2(广播),4-5(地图),6(合并),7(接收器)看起来没问题。但是如何在Akka或反应流术语中实现集合拆分?这不是广播或扁平化,需要将N个元素的集合分成N个独立的子流,这些子流稍后将合并回来。这是如何实现的?
答案 0 :(得分:4)
我建议在一个流程中完成。我知道两个流程看起来更酷但是相信我在设计的简单性方面不值得(我试过)。你可以写这样的东西
import akka.stream.scaladsl.{Flow, Sink, Source, SubFlow}
import scala.collection.immutable
import scala.concurrent.Future
case class Item()
case class Order(items: List[Item])
val flow = Flow[Order]
.mapAsync(4) { order =>
Future {
// Enrich your order here
order
}
}
.mapConcat { order =>
order.items.map(order -> _)
}
.mapAsync(4) { case (order, item) =>
Future {
// Enrich your item here
order -> item
}
}
.groupBy(2, tuple => tuple._1)
.fold[Map[Order, List[Item]]](immutable.Map.empty) { case (map, (order, item)) => map.updated(order, map.getOrElse(order, Nil) :+ item) }
.mapConcat { _.map { case (order, newItems) => order.copy(items = newItems)} }
但即使这种做法也很糟糕。上面的代码或你的设计有很多东西可能出错。如果丰富其中一个订单项目失败,您会怎么做?如果订单对象的丰富失败怎么办?您的信息流会发生什么?
如果我是你,我有Flow[Order]
并在mapAsync
处理其子女,所以至少它保证我没有部分处理过的订单。