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.

+3


source to share


3 answers


You can add this:

f onFailure {
  case e =>
    g onFailure {
      case _ =>
        p.failure(e)
    }
}

      



If both futures fail, it will not make a promise with the same exception as f

. You can do this to create an exception that logs 2 exceptions from f

and g

if needed.

+2


source


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)

}

      

+1


source


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 .

0


source







All Articles