简体   繁体   English

Scala - 如何使用Await.result在Futures上使用Timer而不阻塞

[英]Scala - How to use a Timer without blocking on Futures with Await.result

I have an Rest API provided by akka-http . 我有一个由akka-http提供的Rest API。 In some cases I need to get data from an external database ( Apache HBase ), and I would like the query to fail if the database takes too long to deliver the data. 在某些情况下,我需要从外部数据库( Apache HBase )获取数据,如果数据库花费太长时间来传递数据,我希望查询失败。

One naïve way is to wrap the call inside a Future and then block it with an Await.result with the needed duration. 一种天真的方法是将调用包装在Future ,然后使用具有所需持续时间的Await.result阻止它。

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

object AsyncTest1 extends App {

  val future = Future {
    getMyDataFromDB()
  }

  val myData = Await.result(future, 100.millis)
}

The seems to be inefficient as this implementation needs two threads. 由于此实现需要两个线程,因此似乎效率低下。 Is There an efficient way to do this ? 有一种有效的方法吗?

I have another use case where I want to send multiple queries in parallel and then aggregates the results, with the same delay limitation. 我有另一个用例,我想并行发送多个查询,然后聚合结果,具有相同的延迟限制。

val future1 = Future {
    getMyDataFromDB1()
  }

  val future2 = Future {
    getMyDataFromDB2()
  }

  val foldedFuture = Future.fold(
    Seq(future1, future2))(MyAggregatedData)(myAggregateFunction)
  )

  val myData = Await.result(foldedFuture, 100.millis)

Same question here, what is the most efficient way to implement this ? 同样的问题,实现这个的最有效方法是什么?

Thanks for your help 谢谢你的帮助

One solution would be to use Akka's after function which will let you pass a duration, after which the future throws an exception or whatever you want. 一种解决方案是使用Akka的after函数,它可以让你传递一个持续时间,之后将会抛出异常或任何你想要的东西。

Take a look here . 看看这里 It demonstrates how to implement this. 它演示了如何实现这一点。

EDIT: I guess I'll post the code here in case the link gets broken in future: 编辑:我想我会在这里发布代码,以防链接在将来被破坏:

import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.pattern.after

val system = ActorSystem("theSystem")

lazy val f = future { Thread.sleep(2000); true }
lazy val t = after(duration = 1 second, using = system.scheduler)(Future.failed(new TimeoutException("Future timed out!")))

val fWithTimeout = Future firstCompletedOf Seq(f, t)

fWithTimeout.onComplete {
   case Success(x) => println(x)
   case Failure(error) => println(error)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM