Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Twitter Future timeout doesn't apply to the whole flatMap chain

I'm writing a server end program using Twitter Finagle. I do not use the full Twitter server stack, just the part that enables asynchronous processing (so Future, Function, etc). I want the Future objects to have timeouts, so I wrote this:

Future<String> future = Future.value(some_input).flatMap(time_consuming_function1);
future.get(Duration.apply(5, TimeUnit.SECONDS));

time_consuming_function1 runs for longer than 5 seconds. But future doesn't time out after 5 seconds and it waits till time_consuming_function1 has finished.

I think this is because future.get(timeout) only cares about how long the future took to create, not the whole operation chain. Is there a way to timeout the whole operation chain?

like image 715
stackoverflower Avatar asked Feb 05 '13 15:02

stackoverflower


1 Answers

Basically if you call map/flatMap on a satisfied Future, the code is executed immediately.

In your example, you're satisfying your future immediately when you call Future.value(some_input), so flatMap executes the code immediately and the call to get doesn't need to wait for anything. Also, everything is happening in one thread. A more appropriate use would be like this:

import scala.concurrent.ops._
import com.twitter.conversions.time._
import com.twitter.util.{Future,Promise}

val p = new Promise[String]
val longOp = (s: String) => { 
  val p = new Promise[String]
  spawn { Thread.sleep(5000); p.setValue("Received: " + s) }
  p 
}
val both = p flatMap longOp
both.get(1 second)  // p is not complete, so longOp hasn't been called yet, so this will fail
p.setValue("test")  // we set p, but we have to wait for longOp to complete
both.get(1 second)  // this fails because longOp isn't done
both.get(5 seconds)  // this will succeed
like image 141
rs_atl Avatar answered Oct 13 '22 11:10

rs_atl