2016-05-13 1 views
2

Я пытаюсь включить базу данных в свой http-микросервис.Использование фьючерсов в Scala?

Микросервис имеет функцию getValueFromInternet(val: Foo): Future[Value], которую вызывал мой микросервис по запросу GET. Теперь я хочу, чтобы это произошло так, что функция getValue(val: Foo): Future[Value] сначала запросила бы db, и если база данных не вернет никаких результатов, вызовите getValueFromInternet. Запрос базы данных возвращает Future[Seq[Value2]], где я могу преобразовать Value2 в значение с помощью функции. И если не найдена запись, соответствующая этому значению, возвращается пустой Vector.

Это то, что я пытался до сих пор:

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

Я был бы признателен за любую помощь, предлагая, как я могу это сделать. я реализовал базу данных и microservice независимо друг от друга, и вы можете найти их here и here

+0

Пожалуйста, укажите описание проблемы [минимальное автономное] (http://sscce.org/). Что-то, что мы можем скомпилировать, используя только код, указанный в самом вопросе, гораздо более вероятен, чтобы получить ответ и быть полезным для других. –

+0

о фьючерсах в scala 2.12, ознакомьтесь с этим https://github.com/viktorklang/blog – pedrorijo91

ответ

4

Вы должны использовать flatMap, так что вы хотите делать, если первая операция не возвращает результат также возвращает будущее.

Это как можно ближе к вашему коду при компиляции. Обратите внимание, что вы не можете иметь идентификаторы с именем val в scala, так как это ключевое слово.

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

Вы на самом деле можете, только с backticks;) 'val'. –

+0

Спасибо за помощь. Считаете ли вы, что это возможно, используя recoverWith ?? потому что это похоже на то, что recoveryWith было сделано, чтобы сделать –

+0

@ Łukasz, да, я знаю. Я по-прежнему не рекомендую. @Yash Srivastav, no recoverWith для восстановления неудачного будущего. Однако пустой вектор является успешным результатом БД, а не сбоем. Вам понадобится 'recoverWith', чтобы иметь дело с реальными ошибками DB (получить значение из Интернета, если db недоступен). –