从Akka-stream文档中看,所有流合并选项(merge,mergeSorted,mergePreferred,zipN,zipWithN)通过等待所有合并流都准备好新元素,然后应用合并策略(将元素组合到一个元组,或应用拉链功能等。)
这适用于离线处理(例如,从文件或HTTP中读取数据并将其组合),但它会引入在线处理的延迟。我需要合并由例如数据流生成的数据流。多个Websocket连接,并在任何源流生成值时立即在合并流中提供更新。示例:如果有源流A和B,这里应该是合并流中的内容:
输出流以一些初始值开始,例如(None, None)
。
(A:1) (B:<not ready>) -> (Some(1), None)
(A:2) (B:<not ready>) -> (Some(2), None)
(A:3) (B:1) -> (Some(3), Some(1))
(A:3) (B:2) -> (Some(3), Some(2))
等。同样,当源流的任何立即产生值时,输出流中会出现一个新值。
是否有任何组合来实现这一目标?
答案 0 :(得分:3)
正如评论中所述,Merge
和MergePreferred
阶段确实向下游发射元素,即使并非所有上游都有可用元素。
从你的例子看,你看起来正在寻找压缩源。是的,Zip
仅在具有从其所有上游压缩的元素时才向下游发出压缩元组。为了克服这个问题,你可以解除这个问题。您的源生成Option
s,并在没有其他任何内容发出时让它们发出None
。源包装器可能如下所示:
def asOption[In, Mat](source: Source[In, Mat]): Source[Option[In], Mat] =
Source.fromGraph(GraphDSL.create(source.map(Option(_))) {
implicit builder: GraphDSL.Builder[Mat] => src =>
import GraphDSL.Implicits._
val noneSource = Source.repeat(None)
val merge = builder.add(MergePreferred[Option[In]](1))
src ~> merge.preferred
noneSource ~> merge.in(0)
SourceShape(merge.out)
})
此时您可以像往常一样压缩您的来源。
val src1: Source[Int, NotUsed] = ???
val src2: Source[Int, NotUsed] = ???
val zipped = asOption(src1) zip asOption(src2)