2017-11-30 4 views
2

Ich habe eine Rest API von akka-http zur Verfügung gestellt. In einigen Fällen muss ich Daten von einer externen Datenbank erhalten (Apache HBase), und ich möchte die Abfrage fehlschlagen, wenn die Datenbank zu lange dauert, um die Daten zu liefern.Scala - Wie verwende ich einen Timer ohne auf Futures mit zu warten.Ergebnis

Eine naive Möglichkeit besteht darin, den Anruf in eine Future zu verpacken und dann mit einer Await.result mit der benötigten Dauer zu blockieren.

Das scheint ineffizient zu sein, da diese Implementierung zwei Threads benötigt. Gibt es einen effizienten Weg, dies zu tun?

Ich habe einen anderen Anwendungsfall, wo ich mehrere Abfragen parallel senden möchte und dann die Ergebnisse mit der gleichen Verzögerung Begrenzung aggregiert.

val future1 = Future { 
    getMyDataFromDB1() 
    } 

    val future2 = Future { 
    getMyDataFromDB2() 
    } 

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

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

Die gleiche Frage hier, was ist der effizienteste Weg, dies zu implementieren?

Danke für Ihre Hilfe

Antwort

1

Eine Lösung wäre after Funktion Akka ist zu verwenden, die Sie mit einer Dauer passieren lassen, wonach die Zukunft eine Ausnahme auslöst oder was auch immer Sie wollen.

Werfen Sie einen Blick here. Es zeigt, wie dies implementiert werden kann.

EDIT: Ich denke, ich werde hier den Code für den Fall schreiben die Verbindung in Zukunft gebrochen wird:

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

Vielen Dank für Ihre Hilfe. Ist diese Methode effizienter als das 'Await.result'? Ja, könntest du mir erklären warum? Danke für Ihre Hilfe – ogen

+0

Ja, es ist effizienter als ein 'Await.result', da es den Thread nicht blockiert. Sie suchen nach einer Ausnahme, wenn der DB-Aufruf nach einiger Zeit fehlschlägt. Im obigen Beispiel wird die Zukunft in 1 Sekunde oder weniger abgeschlossen und Sie erhalten ein Ergebnis oder eine Ausnahme. –