2016-05-13 9 views
2

Ich versuche eine Datenbank in meinen http-Microservice einzubauen.Verwenden von Futures in Scala?

Der Microservice hat eine Funktion getValueFromInternet(val: Foo): Future[Value], die von meinem Microservice unter einer GET Anfrage aufgerufen wurde. Nun möchte ich, dass eine Funktion getValue(val: Foo): Future[Value] zunächst eine Datenbank abfragt und die Datenbank getValueFromInternet aufruft, wenn die Datenbank keine Ergebnisse zurückgibt. Die Datenbankabfrage gibt eine Future[Seq[Value2]] zurück, wo ich Value2 mithilfe einer Funktion in Value umwandeln kann. Und wenn zu diesem Wert kein Eintrag gefunden wird, wird eine leere Vector zurückgegeben.

Das ist, was ich bisher versucht habe:

def getValue(val: Foo): Future[Value] = { 
    val resultFuture = db.getValue(val) 
    // 1st attempt. Clearly wrong 
    resultFuture onComplete { 
    case Success(Vector()) => getValueFromInternet(val) 
    case Success(vec) => convertValue2to1(vec.head) 
    } 
    // 2nd attempt. This is also wrong 
    resultFuture match { 
    case Future(Success(Vector())) => getValueFromInternet(val) 
    case Future(Success(vec)) => convertValue2to1(vec.head) 
    } 
} 

Ich würde für jede Hilfe dankbar darauf hindeutet, wie ich dies tun kann. Ich habe die Datenbank und Micro unabhängig implementiert und Sie können sie here und here

+0

Bitte fügen Sie eine [minimale eigenständige] (http://sscce.org/) Beschreibung des Problems. Etwas, das wir nur mit dem in der Frage angegebenen Code kompilieren können, wird viel eher eine Antwort erhalten und für andere nützlich sein. –

+0

über Futures in Scala 2.12, überprüfen Sie diese https://github.com/viktorklang/blog – pedrorijo91

Antwort

4

Sie haben verwenden flatMap, da das, was Sie wollen tun, wenn die erste Operation nicht wieder ein Ergebnis auch einen zukünftigen Erträge finden.

Dies ist so nah wie möglich an Ihrem Code während der Kompilierung. Beachten Sie, dass Sie in scala keine Bezeichner val haben können, da dies ein Schlüsselwort ist.

def getValue(v: Foo)(implicit ec: ExecutionContext): Future[Value] = { 
    val resultFuture: Future[Seq[Value2]] = db.getValue(v) 
    resultFuture.flatMap { vec => 
    if(vec.isEmpty) 
     getValueFromInternet(v) 
    else 
     Future.successful(convertValue2to1(vec.head)) 
    } 
} 
+0

Sie können tatsächlich, nur mit Backticks;) 'val'. –

+0

Danke für die Hilfe. Denkst du, das ist möglich mit recoverMith ?? denn das scheint genau das zu sein, was mit –

+0

@ Łukasz gemacht wurde, ja ich weiß. Ich würde es immer noch nicht empfehlen. @ Yash Srivastav, Nein. RecoverWith dient zur Wiederherstellung einer fehlgeschlagenen Zukunft. Ein leerer Vektor ist jedoch ein erfolgreiches Ergebnis der Datenbank, kein Fehler. Sie würden 'recoverWith' benötigen, um auch mit echten DB-Fehlern umzugehen (Wert aus dem Internet holen, wenn db nicht verfügbar ist). –