Выполнять несколько задач параллельно, выбирать ответ из первого выполненного

У меня есть n разные источники, чтобы, скажем, узнать курс доллара к евро. Пусть n = 3 и источниками будут Google, Yahoo, MyRates с соответствующими методами:

def getYahooRate:Double = ???
def getGoogleRate:Double = ???
def getMyRate:Double = ???

Я хочу запросить курс доллара США к евро таким образом, чтобы все n источника опрашивались параллельно и немедленно возвращался первый полученный ответ. Если никто не отвечает в течение указанного периода времени, создается исключение.

Каков канонический способ реализовать это с помощью Scala (и, если необходимо, Akka)?

Есть ли какой-нибудь библиотечный метод, который делает большую часть этого?

РЕДАКТИРОВАТЬ: вот что я пробовал. Некоторые комментарии к коду будут оценены:

Это чем-то похоже на параллельную версию trycatch из этого вопроса SO. Код для приведенного ниже метода основан на этом ответе SO

type unitToT[T] = ()=>T

def trycatchPar[B](list:List[unitToT[B]], timeOut:Long):B = { 
    if (list.isEmpty) throw new Exception("call list must be non-empty")
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent._
    import scala.concurrent.duration._
    import scala.util.Failure
    import scala.util.Success

    val p = promise[B]
    val futures = list.map(l => Future{l()})
    futures foreach {
       _ onComplete {
         case s @ Success(_) => {
             // Arbitrarily return the first success
             p tryComplete s           
           }
         case s @ Failure(_) =>
       }
    }
    Await.result(p.future, timeOut millis)
}

person Jus12    schedule 18.04.2016    source источник


Ответы (1)


Вы можете использовать Future.firstCompletedOf

val first = Future.firstCompletedOf(futures)
Await.result(first, timeOut.millis)
person drexin    schedule 18.04.2016
comment
После небольшого испытания это не ведет себя так, как ожидалось. Если первый выдает ошибку, он возвращает ее вместо того, чтобы ждать успеха, в отличие от кода, который я вставил. - person Jus12; 13.08.2016