Skip to content

Instantly share code, notes, and snippets.

@carter437
Last active August 29, 2015 14:06
Show Gist options
  • Save carter437/daa209c27c140e42d381 to your computer and use it in GitHub Desktop.
Save carter437/daa209c27c140e42d381 to your computer and use it in GitHub Desktop.
Basic Future takeFirstMatch
object FutureOps extends FutureOps
trait FutureOps {
def takeFirstMatch[A](futures: Traversable[Future[A]], predicate: A => Boolean): Future[Option[A]] = {
val promise = Promise[Option[A]]
def aggregateFailures(futuresToFailureCheck: Traversable[Future[A]], exceptions: Seq[Throwable]): Unit = {
futuresToFailureCheck match {
case Nil => {
Promise.failed(new RuntimeException(s"All Futures Failed - StackTraces: ${exceptions.zipWithIndex.map { case (e, i) => s"Exception ${i} ${ExceptionUtils.getStackTrace(e)}"}}"))
}
case head :: tail => head onFailure { case ex => aggregateFailures(tail, exceptions :+ ex)}
}
}
futures.foreach(_.onSuccess { case a if predicate(a) => promise.trySuccess(Some(a))})
aggregateFailures(futures,Nil)
Future.sequence(futures) onComplete {
case _ => {
val completeSuccess = futures.map(_.value).map(_.get).filter(_.isSuccess)
if (!completeSuccess.isEmpty) {
completeSuccess.map(_.get).find(predicate) match {
case Some(value) => promise.trySuccess(Some(value)) //just in case this executed first
case _ => promise.trySuccess(None)
}
}
}
}
promise.future
}
def takeFirst[A](futures: Traversable[Future[A]]) = takeFirstMatch(futures,{ A => true})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment