Skip to content

Instantly share code, notes, and snippets.

@kermitas
Last active October 22, 2015 23:31
Show Gist options
  • Save kermitas/c102d361204978ea66a1 to your computer and use it in GitHub Desktop.
Save kermitas/c102d361204978ea66a1 to your computer and use it in GitHub Desktop.
Future.sequence() is fine but it will fail if any of passed Futures will fail. Sometimes we would like to have the same functionality but it should not fail - it should just have a collection of completed Futures (completed with Success or Failure).
package scala.concurrent
import scala.util.{ Try, Success }
object FutureUtils {
/**
* @return resulted future will be completed when all passed futures will be completed (either with Success or Future)
*/
def completeAll[T](fs: Future[T]*)(implicit ec: ExecutionContext): Future[Seq[Future[T]]] = Future.successful(fs).flatMap { fs =>
if (fs.isEmpty) {
Future.successful(fs)
} else {
import java.util.concurrent.atomic.AtomicInteger
val remaining = new AtomicInteger(fs.length)
val p = Promise[Seq[Future[T]]]()
fs.foreach {
_ onComplete {
case _ => if (remaining.decrementAndGet == 0) p.complete(Success(fs))
}
}
p.future
}
}
/**
* Converts passed futures to tries.
*
* @param fs all passed futures should be completed
*/
def futureToTry[T](fs: Future[T]*)(implicit ec: ExecutionContext): Seq[Try[T]] = fs.map(_.value).map {
_ match {
case Some(r) => r
case None => throw new Exception("All passed futures should be completed before calling this method.")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment