Home > Software engineering >  Throwing exception or fail the task using Future.failed
Throwing exception or fail the task using Future.failed

Time:12-17

I am using scala futures to poll API status . Continue to poll till return success or fail. How ever when any batch fails, it should throw error and stop the program.

I am not able throw error either by throw ( exception) or Future.successful(false) or Future.failed(new Exception("error")) .


package FutureScheduler

import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global


object delayTest extends App {

  import scala.concurrent.Future
  import scala.concurrent.duration._
  import scala.concurrent.ExecutionContext.Implicits.global


  def getStatus(batchId: String): String = {
    print(s" $batchId ${System.currentTimeMillis()} continue \n")
    batchId match {
      case "batch1" => "success"
      case "batch2" => "failed"
      case "batch2" => "success" 
    }
  }


  def waitTask(batch: (String, Int)
              ): Future[Boolean] =
    Delayed(x.seconds)(getStatus(batch._1)).flatMap {
      case "success" =>
        print(s"\n${batch._1} succeeded for ${batch._2}")
        Future.successful(true)
      case "failed"  =>
        print(s"\n${batch._1} failed for ${batch._2}")
        Future.failed(new Exception("error"))
        throw new RuntimeException("errored")
      case _ => {
        waitTask(batch)
      }
    }


  val statusList =  List(Some("batch1", 123), None, Some("batch2", 124)).flatten

  val y = 1
  val x = 5

  try {
    Await.ready(Future.traverse(statusList)((waitTask _)), y.minutes)
  }
  catch {
    case e: Exception => println("caught error")
  }

  print("\nbye now")

}

import scala.concurrent.duration._

import scala.concurrent.{Future, Promise}

object Delayed {
  import java.util.{Timer, TimerTask}
  private val timer = new Timer
  def apply[T](delay: Duration)(task: => T): Future[T] = {
    val promise = Promise[T]()
    val tt = new TimerTask {
      override def run(): Unit = promise.success(task)
    }
    timer.schedule(tt, delay.toMillis)
    promise.future
  }
}

CodePudding user response:

The throw is happening inside the Future returned by Delayed so it will be caught by that Future.

You need to turn Await.ready into Await.result and then look at the value that it returns to get the result of the test.

  • Related