6

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?

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
stackoverflower
  • 3,885
  • 10
  • 47
  • 71

1 Answers1

2

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
rs_atl
  • 8,935
  • 1
  • 23
  • 28