I need to call into a service that may or not return timely results. I\'d like to be able to write
val result = runWithTimeout(5000, valReturnedOnTimeout) {
Something that hasn't been mentioned yet is awaitEither, a method on the actors package's Futures object. awaitEither returns the result from the first of a pair of futures to complete, so for example something like this could be used:
awaitEither(future{task}, alarm(timeoutPeriod))
and then dressed up in a method as suggested:
def runWithTimeout[T](timeoutPeriod: Int, timeoutValue: T)(task: => T) = {
awaitEither(future{task}, alarm(timeoutPeriod)) match {case () => timeoutValue case x => x}
}
alarm returns Unit which is assignable to a val of type Any so awaitEither returns something that can be pattern matched against.
You can start it in a new Thread and then wait for it to finish with Thread.join. If you pass a parameter to join, it waits at most that many milliseconds.
val t = new Thread {
override def run() {
//...
}
}
t.start()
t.join(5000)
You could use a future
import scala.actors.Futures._
val myfuture =
future {
Thread.sleep(5000)
println("<future>")
"future "
}
awaitAll(300,myfuture ) foreach println _
But also have a look at Circuit Breaker for Scala which is a implementation of the Circuit Breaker Pattern. Basically it lets you control the timeout and what should happen if a failure occurs accessing an external resource
Usage looks like this in Scala (from the readme) :
. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(timeout=100,failureThreshold=10))
. . .
class Test extends UsingCircuitBreaker {
def myMethodWorkingFine = {
withCircuitBreaker("test") {
. . .
}
}
def myMethodDoingWrong = {
withCircuitBreaker("test") {
require(false,"FUBAR!!!")
}
}
}
The post above
import scala.concurrent.ExecutionContext.Implicits.global import
scala.concurrent._ import scala.concurrent.duration._
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
Await.result(Future(f), timeoutMs milliseconds).asInstanceOf[Option[T]] }
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeout(timeoutMs)(f).getOrElse(default) }
didn't work for me on Scala 2.11.
Following modified version works for me:
def runWithTimeout[T](timeout: Long)(f: => T): Option[T] = {
Option.apply(Await.result(Future(f), timeout seconds))
}
Might Futures and its alarm
do the trick?
With credit to the other answers - in the absence of any standard library function, I've gone down the Futures route.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
Some(Await.result(Future(f), timeoutMs milliseconds))
}
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeout(timeoutMs)(f).getOrElse(default)
}
So that
@Test def test {
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
runWithTimeout(50, "no result") { "result" } should equal ("result")
runWithTimeout(50, "no result") { Thread.sleep(100); "result" } should equal("no result")
}
I'd be grateful for any feedback as to whether this is a good Scala style!