如何将Future of Future任务转换为Enumerator,这将消耗最新的完整任务

时间:2014-11-20 13:30:46

标签: scala concurrency parallel-processing enumerator

我正在进行昂贵的计算,我是批处理的,并返回分块的HTTP响应。定期有一些计算比其他计算更贵[&34;它可能会导致客户端超时。

目前Enumerator中的计算列表如下:

def processBatch(batch: List[B]): Enumerator[A] = {
    val listOfCalculations:List[Future[A]] = batch.map(....)
    val futureList: Future[List[A]] = Future.sequence(listOfFutures)
    Enumerator.flatten(futureList.map(Enumerator.enumerate(_)))
}

通过此实现,Enumerator仅在Future列表完成后才输入。这样做并不好,因为可能存在一些现成值,等待昂贵的任务完成。

我想知道是否有更好的方法可以做到这一点 - 只要它们在完成时就向Enumerator提供值,而不是作为一个批次,在所有Futures complition上?

2 个答案:

答案 0 :(得分:2)

Future.sequence意味着"所有这些未来的清单,当它们完成时#34;所以你不能使用它。

有一种方法可以在play.api.libs.iteratee.Concurrent.unicast中找到一个更有必要的枚举器,你可以使用它,所以一旦得到结果,就会将它推入a Channel。这将代表命令式推送,作为一个可以使用iteratee使用的枚举器。

这样第一个完整的结果首先到达等。

You can find the docs for it here

答案 1 :(得分:1)

您可以使用Enumerator.unfoldM。类似的东西:

val listOfCalculations:List[Future[A]] = ...
Enumerator.unfoldM(0) { i =>
  if(i < listOfCalculations.length)
    listOfCalculations(i).map(a => Some((i + 1, a)))
  else Future.successful(None)
}

这有点像折叠。 i跟踪我们在列表中的位置;每次调用我们的映射器时,我们都会从列表中获得下一个未来并使用新索引返回它。

相关问题