2016-04-18 3 views
0

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

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

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

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

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

EDIT: Вот что я пробовал. Некоторые комментарии к этому кодексу будут оценены:

Это несколько напоминает параллельную версию trycatch от this SO question. Код ниже метод основан на this SO answer

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

ответ

3

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

val first = Future.firstCompletedOf(futures) 
Await.result(first, timeOut.millis) 
+0

Сладкий и простой! – Jus12

+0

После небольшого пробного периода это не ведет себя так, как ожидалось. Если первый дает сбой, он возвращает это вместо ожидания успеха, в отличие от кода, который я вставил. – Jus12