How do I get hold of exceptions thrown in a Scala Future?

后端 未结 6 1134
我在风中等你
我在风中等你 2020-12-06 10:30

I\'ve been working up my answer to Is there a standard Scala function for running a block with a timeout?, and have run into a problem if an exception is thrown in a Future.

6条回答
  •  囚心锁ツ
    2020-12-06 10:33

    Working my way through @Rex Kerr's suggestion, I've created

    object Timeout {
    
      val timeoutException = new TimeoutException
    
      def runWithTimeout[T](timeoutMs: Long)(f: => T) : Either[Throwable, T] = {
        runWithTimeoutIgnoreExceptions(timeoutMs)(exceptionOrResult(f)) match {
          case Some(x) => x
          case None => Left(timeoutException)
        }
      }
    
      def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : Either[Throwable, T] = {
        val defaultAsEither: Either[Throwable, T] = Right(default)
        runWithTimeoutIgnoreExceptions(timeoutMs, defaultAsEither)(exceptionOrResult(f))
      }
    
      def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long)(f: => T) : Option[T] = {
        awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
      }
    
      def runWithTimeoutIgnoreExceptions[T](timeoutMs: Long, default: T)(f: => T) : T = {
        runWithTimeoutIgnoreExceptions(timeoutMs)(f).getOrElse(default)
      }
    
      private def exceptionOrResult[T](f: => T): Either[Throwable, T] = 
        try { 
          Right(f) 
        } catch { 
          case x => Left(x)
        }
    }
    

    so that

      @Test def test_exception {
        runWithTimeout(50) { "result" }.right.get should be ("result")
        runWithTimeout(50) { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
        runWithTimeout(50) { Thread.sleep(100); "result" }.left.get should be (Timeout.timeoutException)
    
        runWithTimeout(50, "no result") { "result" }.right.get should be ("result")
        runWithTimeout(50, "no result") { throw new Exception("deliberate") }.left.get.getMessage should be ("deliberate")
        runWithTimeout(50, "no result") { Thread.sleep(100); "result" }.right.get should be ("no result")
    
    }
    

    Again, I'm a bit of a Scala novice, so would welcome feedback.

提交回复
热议问题