2017-11-30 8 views
2

私はakka-httpによって提供されるRest APIを持っています。場合によっては、外部データベース(Apache HBase)からデータを取得する必要があります。データベースがデータを配信するのに時間がかかりすぎると、クエリが失敗することがあります。Scala - Await.resultを使用して先物をブロックすることなくタイマーを使用する方法

1つの単純な方法は、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) 
} 

この実装には2つのスレッドが必要であるため、非効率的なようです。これを行う効率的な方法はありますか?

私は、複数のクエリを並列に送信し、同じ遅延制限で結果を集約する別の使用例があります。

val future1 = Future { 
    getMyDataFromDB1() 
    } 

    val future2 = Future { 
    getMyDataFromDB2() 
    } 

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

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

これを実行する最も効率的な方法は何ですか?

おかげであなたの助け

答えて

1

一つの解決策は、あなたが将来的にはあなたが好きな例外をスローまたはその後の期間を、渡すようになるアッカのafter機能を使用することです。

hereをご覧ください。これを実装する方法を示します。

EDIT: 私はリンクが将来的に破損した場合などには、ここでのコードを投稿しますね:あなたの助けを

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) 
} 
+0

感謝。このメソッドは 'Await.result'より効率的ですか?はい、なぜ私に説明できますか?あなたの助けをありがとう – ogen

+0

はい、スレッドをブロックしないので、 'Await.result'より効率的です。 DBコールがしばらくして失敗した場合、上記の例では、未来は1秒以内に完了し、結果または例外が発生することになります。 –

関連する問題