Kevin Meredith Kevin Meredith - 16 days ago 6
Scala Question

`akka.pattern.after` - Understanding `duration` Argument?

Using Scala

2.11.8
, given a
Future
that sleeps
5
seconds before returning
()
, I called
akka.pattern.ask
with a time-out of
1
second:

import scala.concurrent.duration._
import scala.concurrent._
import akka.actor.ActorSystem
import scala.concurrent.ExecutionContext.Implicits.global
import akka.pattern.after

val system = ActorSystem.create()

after( FiniteDuration(1, SECONDS), system.scheduler)( Future{ Thread.sleep( 5000 ); () } )
res15: scala.concurrent.Future[Unit] = List()

// roughly 5 seconds later, I see:

scala> res15
res22: scala.concurrent.Future[Unit] = Success(())


Why doesn't
res15
return a
Failure
since the
Future
does not complete until 5 seconds, however its timeout is 1 second?

Answer

After method will run your future after some delay. duration is not timeout, its the starting delay. After method internally uses scheduleOnce method of actorSystem schedular.

After is very interesting method which starts evaluating/executing your future expression (i.e value) only after the certain given duration.

If the given duration is very small then its starts executing the value immediately.

As value is a call by name parameter the value is not immediately evaluated. value will be evaluated only when explicitly called by the name value.

Here is the code from akka lib.

def after[T](duration: FiniteDuration, using: Scheduler)(value: ⇒ Future[T])(implicit ec: ExecutionContext): Future[T] =
  if (duration.isFinite() && duration.length < 1) {
    try value catch { case NonFatal(t) ⇒ Future.failed(t) }
  } else {
   val p = Promise[T]()
   using.scheduleOnce(duration) { p completeWith { try value catch { case NonFatal(t) ⇒ Future.failed(t) } } }
   p.future
}

Basically your duration will trigger the following code

using.scheduleOnce(duration) { p completeWith { try value catch { case NonFatal(t) ⇒ Future.failed(t) } } }

The above code will start executing the future after delay(duration is the delay.).

Important observations:

note that value is a call by name parameter. value will be evaluated when called by name that means your future will not be start executing until and unless value is called explicitly. value is called inside try because value could be a multi line expression which contains lot of code and which returns a future finally.

Promise (see in the code) will make you wait in a non blocking fashion till the future is completed its execution. promise.future will only complete when given future completes.