Sequencing "The future with a timeout"

I used the TimeoutScheduler introduced in Scala Futures - built-in timeout? .

However, now my program does not end as before without TimeoutScheduler .

I have two Future s: res1 and res2 . Both with a timeout of 15 seconds. In the end, I execute the Future sequence to shut down the HTTP artist normally in the onComplete callback. Without using withTimeout program ends immediately after http.shutdown . But using withTimeout not. What for? There must be some further future ...

 import java.net.URI import scala.util.{ Try, Failure, Success } import dispatch._ import org.json4s._ import org.json4s.native.JsonMethods._ import com.typesafe.scalalogging.slf4j.Logging object Main extends App with Logging { import scala.concurrent.ExecutionContext.Implicits.global val http = Http val github = host("api.github.com").secure import timeout._ import scala.concurrent.duration._ import scala.language.postfixOps import scala.collection.JavaConverters._ val req: dispatch.Req = github / "users" / "defunkt" val res1 = http(req > dispatch.as.Response(_.getHeaders().get("Server").asScala)) withTimeout (15 seconds) recover { case x => logger.debug("Error1: " + x.toString) Nil } val res2 = http(req > dispatch.as.Response(_.getHeaders().get("Vary").asScala)) withTimeout (15 seconds) recover { case x => logger.debug("Error2: " + x.toString) Nil } Future.sequence(res1 :: res2 :: Nil) onComplete { case _ => http.shutdown() // without using `withTimeout` the program terminated after `http.shutdow` TimeoutScheduler.timer.stop() // thanks to @cmbaxter } } object timeout { import java.util.concurrent.TimeUnit import scala.concurrent.Promise import scala.concurrent.duration.Duration import org.jboss.netty.util.Timeout import org.jboss.netty.util.TimerTask import org.jboss.netty.util.HashedWheelTimer import org.jboss.netty.handler.timeout.TimeoutException // cf. /questions/119602/scala-futures-built-in-timeout object TimeoutScheduler { val timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS) def scheduleTimeout(promise: Promise[_], after: Duration) = { timer.newTimeout(new TimerTask{ def run(timeout: Timeout){ promise.failure(new TimeoutException("Operation timed out after " + after.toMillis + " millis")) } }, after.toNanos, TimeUnit.NANOSECONDS) } } implicit class FutureWithTimeout[T](f: Future[T]) { import scala.concurrent.ExecutionContext def withTimeout(after: Duration)(implicit ec: ExecutionContext) = { val prom = Promise[T]() val timeout = TimeoutScheduler.scheduleTimeout(prom, after) val combinedFut = Future.firstCompletedOf(List(f, prom.future)) f onComplete { case result => timeout.cancel() } combinedFut } } } 

Any suggestions are welcome, Best, / nm

+4
scala future scala-dispatch
Feb 24 '14 at 9:11
source share
1 answer

If you used my code exactly as described, then I assume that the Netty HashedWheelTimer , which is under the TimeoutScheduler object, is not interrupted. You can try explicitly calling stop on it by calling http.shutdown as follows:

 TimeoutScheduler.timer.stop 

Now, if you want Netty HashedWheelTimer use the daemon stream, you can use one of its constructors (I see them in 3.6.6-Final), which accepts ThreadFactory , and then uses the custom ThreadFactory , which sets the daemon flag to true.

+4
Feb 24 '14 at 12:59
source share



All Articles