How to fulfill a promise in Scala
The Scala documentation provides an example of how to choose a future that is faster with promises.
http://docs.scala-lang.org/overviews/core/futures.html#promises
def first[T](f: Future[T], g: Future[T]): Future[T] = {
val p = promise[T]
f onSuccess {
case x => p.trySuccess(x)
}
g onSuccess {
case x => p.trySuccess(x)
}
p.future
}
This function returns the future which succeeds first, and if one of them fails, it never completes.
Is it possible to change this so that even if another future fails, then the second one will be returned if it succeeds, and if both of them succeed, then the faster one will be chosen, as the code now does.
source to share
I recommend you follow Alvin Alexander's guidelines for futures and promises in Scala here
I believe this is the best way to work with futures
package futures
import scala.concurrent.{Future => ConcurrentTask} // rename
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import Utils.sleep
object FutureAsConcurrentTask extends App {
// run some long-running task (task has type Future[Int] in this example)
val task = ConcurrentTask {
Cloud.executeLongRunningTask
}
// whenever the task completes, execute this code
task.onComplete {
case Success(value) => println(s"Got the callback, value = $value")
case Failure(e) => println(s"D'oh! The task failed: ${e.getMessage}")
}
// do your other work
println("A ..."); sleep(100)
println("B ..."); sleep(100)
println("C ..."); sleep(100)
println("D ..."); sleep(100)
println("E ..."); sleep(100)
println("F ..."); sleep(100)
}
source to share
Here's a basic model for choosing the fastest futures or timeouts if they are all too slow:
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }
import akka.actor._
import akka.pattern.after
object GetFastestFutureOrTimeout extends App {
val e = new TimeoutException("TimeoutException")
val system = ActorSystem("GetFastestFutureOrTimeout")
val f1 = Future { Thread.sleep(200); "this is f1" }
val f2 = Future { Thread.sleep(100); "this is f2" }
val timeoutFuture = after(500.milliseconds, using = system.scheduler) { Future.failed(e) }
val f = Future.firstCompletedOf(f1 :: f2 :: timeoutFuture :: Nil)
f onComplete {
case Success(msg) => println(msg)
case Failure(err) => println("An error occured: " + err.getMessage)
}
}
Will print "this is f2". If timeoutFuture timeout was changed to 50, it would print "An error occurred: TimeoutException".
Under the hood, firstCompletedOf uses a Promise to return the value of the first Future that is complete, see https://github.com/scala/scala/blob/v2.11.6/src/library/scala/concurrent/Future.scala#L503 .