Is there a standard Scala function for running a block with a timeout?

后端 未结 6 449
伪装坚强ぢ
伪装坚强ぢ 2020-12-19 02:40

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) {         


        
相关标签:
6条回答
  • 2020-12-19 02:57

    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.

    0 讨论(0)
  • 2020-12-19 02:59

    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)
    
    0 讨论(0)
  • 2020-12-19 03:05

    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!!!")
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-19 03:05

    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))
      }
    
    0 讨论(0)
  • 2020-12-19 03:11

    Might Futures and its alarm do the trick?

    0 讨论(0)
  • 2020-12-19 03:23

    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!

    0 讨论(0)
提交回复
热议问题