我有一个Source
,提供类型A的元素。
我有一个Flow
,它接收类型B的元素。
我想做的是,当流接收到输入时,来自源的下一个元素作为流的输出发出。
我目前的操作方式是将源连接到Sink.queue
。然后,针对流中的每个元素,在其上进行映射,丢弃输入,并从队列中提取下一个值。队列为空后,我就完成了流程。
我觉得应该缺少一个更简单的方法。可能有一些内置的机制允许输入触发源中的元素。
例如:
val source = ... some akka streams source
val queue = source.grouped(limit.toInt).runWith(Sink.queue[Seq[DataFrame]])
Flow[Message]
.prepend(Source.single(TextMessage.Strict("start")))
.collect {
case TextMessage.Strict(text) => Future.successful(text)
case TextMessage.Streamed(textStream) => textStream.runFold("")(_ + _).flatMap(Future.successful)
}
// swallow the future of the incoming message's text
.mapAsync(1)(identity)
// take the next batch
.mapAsync(1)(_ => queue.pull())
// swallow the option monad, and add in an end or page-end message
.collect {
case Some(batch) if batch.size == limit => batch.toList :+ pageend
case Some(batch) => batch.toList :+ end
case None => List(end)
}
// flatten out the frames
.mapConcat(identity)
end
和pageend
只是ui使用的特殊框架。问题的关键部分在于队列的使用。