Timeout non-blocking futures

949 views
Skip to first unread message

Tsume

unread,
Apr 25, 2013, 8:58:44 AM4/25/13
to akka...@googlegroups.com
Is it possible for me timeout a non-blocking future or is it only possible with a blocking future?
I wish to send a request to a database, while the actor does some calculations. If the data is not received at a certain point I'd like timeout the future and maybe try again.

Another question is how does the onFailure callback get activated? Is it called when the actor which is suppose to respond to the future throws an exception?

Akka Team

unread,
Apr 25, 2013, 11:53:38 AM4/25/13
to Akka User List
Hi Tsume,

there is no such thing as a blocking Future in Akka; if you are referring to java.util.concurrent.Future, then that also does not have a timeout per se (you can limit the time you await its result, but that is equally possible with scala.concurrent.Future).

Sending a request to a database typically (sadly) is a synchronous blocking API call (e.g. JDBC) which also cannot be interrupted, so the only thing you can do is to discard the result it may produce and try anew.

import akka.dispatch.Futures;
import akka.pattern.Patterns;

final Future<Result> f1 = ...; // e.g. wrap a JDBC call here
final Future<Result> t1 = Patterns.after(timeout, context.system.scheduler, context.dispatcher, Futures.failed(new TimeoutException));
final Future<Result> f2 = Futures.firstCompletedOf(Arrays.asList(new Future<Result>[] { f1, t1 }));
final Future<Result> result = f2.recover(new Recover<Result>() {
  @Override public Result recover(Throwable failure) {
    if (failure instanceof TimeoutException) {
      // try again, fall back to different data source, whatever
  }
}

Assuming that f1 in the above example results from a Patterns.ask() operation, it will be completed with the timeout given there, so the special handling with t1 and f2 is not necessary. Otherwise failures are not automatically propagated, the Future will only be completed with what the actor sends. In order to send a failure (and thus fail the Future) there is a special wrapper class akka.actor.Status.Failure which needs to be sent back.

Regards,

Roland



--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://akka.io/faq/
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Akka Team
Typesafe - The software stack for applications that scale
Blog: letitcrash.com
Twitter: @akkateam

Tsume

unread,
May 5, 2013, 1:39:05 PM5/5/13
to akka...@googlegroups.com
Hi Roland.

Sorry for the late follow up but I have a question regarding how to handle a timeout exception when using a blocking call (I haven't been able to generate a timeout in my small scale testing yet, so not sure if I'm doing it right)
In reference to the blocking example given, how would I handle a timeout exception?

  1.  
  2. implicit val timeout = Timeout(5 seconds)
  3. val future = actor ? msg // enabled by the “ask” import
  4. val result = Await.result(future, timeout.duration)
  5. actor2 !result

Would I use the onFailure & onComplete callbacks or would I use a try & catch statement like this:

try{
future = actor ? msg
val result = Await.result(future, timeout.duration).asInstanceOf[String]
  actor2 ! result
}  catch {
   case e:TimeoutException => doSomething
}

Just to make it clear if a timeout exception does occur I don't want a message to be sent to actor2.
I read the recover method is like a try/catch statement, my difficulty is understanding how to use it given the example above.

Roland Kuhn

unread,
May 5, 2013, 2:11:09 PM5/5/13
to akka...@googlegroups.com
Hi Tsume,

you should rather use non-blocking composition (i.e. consider every Await.result() to be a bug unless carefully justified):

actor ? msg onSuccess ( actor2 ! _ )

but since this is a common thing to do there is another pattern for it:

import akka.pattern.pipe
...
actor ? msg pipeTo actor2 onFailure {
  case ex: TimeoutException => // do something
}

But beware: doing something in there MUST NOT access the actor’s internal state or call the actor’s methods; if the actor needs to do something upon timeout then perhaps do something like the following

val me = self // “self” becomes invalid after a restart (at least as seen from the old incarnation)
(actor ? msg pipeTo actor2).failed foreach (_ => me ! MyTimeout)

This is about the extent to which I’d recommend using Futures; if you want to chain more steps and do more error handling then I’d recommend spawning a dedicated Actor which explicitly goes through the individual steps (e.g. using FSM or a become()-based state machine with ReceiveTimeout).

Regards,

Roland

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://akka.io/faq/
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Empowering professional developers to build amazing apps.
twitter: @rolandkuhn

See you at Scala Days 2013 in NYC!
June 10th - June 12th
www.scaladays.org

Derek Williams

unread,
May 5, 2013, 2:18:41 PM5/5/13
to Akka User List
You can use onFailure and onComplete to detect a timeout, and you can use recover or andThen. For side effects, onComplete or andThen will work best:

import scala.util.{Success, Failure}

implicit val timeout = Timeout(5 seconds)

actor ? msg onComplete {
  case Success(result: String)      => actor2 ! result
  case Failure(e: TimeoutException) => doSomething
}

You can also use the recover method, along with map and flatMap if you want to avoid side effects.



--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://akka.io/faq/
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Derek Williams

Tsume

unread,
May 5, 2013, 3:26:40 PM5/5/13
to akka...@googlegroups.com
Thanks for the advice, Roland & Derek

How does the onComplete (or the is it ask ) method know that I'm using a timer for the future?
In the case of the Await.result I can obviously see that I state time in the call. But for the examples which you have both provided I do not see how the future knows that the response should be completed in a certain amount of time. Does simply stating
 implicit val timeout = Timeout(5 seconds)
before the future do this?

Roland Kuhn

unread,
May 5, 2013, 3:39:10 PM5/5/13
to akka...@googlegroups.com
Hi Tsume,


Regards,

Roland

Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Empowering professional developers to build amazing apps.
twitter: @rolandkuhn

Tsume

unread,
May 6, 2013, 10:58:37 AM5/6/13
to akka...@googlegroups.com
Thanks
Reply all
Reply to author
Forward
0 new messages