当某些可能超时时,如何在多个Future等待中检索部分结果? [英] How to retrieve partial result in multiple Future wait when some might time-out?

查看:300
本文介绍了当某些可能超时时,如何在多个Future等待中检索部分结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在scala的play框架上使用FUTURE.但是在合并多个期货时,如果超时,我很难获得最终结果的一部分.这是我的代码的作用.它有两个未来分别查询两个提供程序.然后使用for/yield语句合并结果.然后等待带有超时值的结果.当两个提供程序按时答复查询时,它可以正常工作.但是,如果只有一个提供者按时答复,我知道等待将超时,但是在这种情况下,我仍然需要检索从另一提供者按时答复的数据.我怎么做?

I am using FUTURE in scala on play framework. But I have difficulty to get part of the final result in case of timeout when merging multiple futures. Here is what my code does. It has two future to query two providers respectively. And then use a for/yield statement to merge the results. And then await for the result with a time out value. It works fine when two providers reply to the query on time. However, if just one provider reply on time, I know the await will timeout but in this case I still need to retrieve the data returned from the other provider which replied on time. How do I do that?

val pool = Executors.newCachedThreadPool()
implicit val ec = ExecutionContext.fromExecutorService(pool)

var future1 = Future(QueryProvider(provider1, request1))  
var future2 = Future(QueryProvider(provider2, request2))  

val future = for {
    result1 <- future1
    result2 <- future2
 } yield (Merge(result1, result2))

 val duration = Duration(60000, MILLISECONDS)

 try{
     result = Await.result(future, duration).asInstanceOf[string]       
 }

catch{
    case _: Exception => println("time out...") 
    //Here how can I retrieve provider1's result if only provider2 timeout???***
 }

推荐答案

您可以使用

You could use after from akka instead of blocking Await.result:

val timeout =
  akka.pattern.after(FiniteDuration(60000, MILLISECONDS), using = system.scheduler){
    Future.successful(None)
  }

val resFuture = for {
    result1 <- Future firstCompletedOf Seq(future1.map{Some(_)}, timeout)
    result2 <- Future firstCompletedOf Seq(future2.map{Some(_)}, timeout)
} yield (result1, result2)

val result = resFuture map {
  case (Some(r1), Some(r2)) => Merge(r1, r2)
  case (Some(r1), None) => PartialResult1(r1)
  case (None, Some(r2)) => PartialResult2(r2)
  case _ => EmptyResult
}

在这种情况下,resFuture将在60秒内完成,您可以处理部分结果.另外,您不需要Play中的Await-您可以使用 Async .

In this case resFuture will be completed in 60 seconds and you can process partial result. Also you don't need Await in Play - you could use Async.

如果您有许多相同类型的等效期货,可以这样使用:

In case you have many equivalent futures of the same type you could use it like this:

val futures: Seq[Future[Int]] = ???
val futureWithTimeout =
  futures.map{ f => Future firstCompletedOf Seq(f.map{Some(_)}, timeout) }

val result: Future[Seq[Option[Int]]] = Future.sequence(futureWithTimeout)

// In case you need to know index of completed or not completed future
val indexedResults = result.zipWithIndex

// In case you just need only completed results
val completedResults: Future[Seq[Option[Int]]] = result.map{_.flatten}

此处的类型仅用于说明.

Types here are only for illustration.

这篇关于当某些可能超时时,如何在多个Future等待中检索部分结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆