You all must be wondering timeouts in Futures, how is that possible? Don’t worry this is the right place to explore what do we mean by Futures with a timeout.
I had encountered an issue of finding out if we can provide timeouts to futures in Scala without actually blocking them and guess what, this is possible. In this blog, we will be talking about how we can provide timeouts to the scala futures and provide an illusion of blocking the future.
We all know that Scala futures do not have any built-in timeout and we can’t even provide any timeout to them until we block the future explicitly by using scala.concurrent.Await which is undesirable.
The above code results in the following output:
java.util.concurrent.TimeoutException: Futures timed out after [2 seconds] at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:255) at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:259) at scala.concurrent.Await$.$anonfun$result$1(package.scala:215) at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53) at scala.concurrent.Await$.result(package.scala:142) ... 36 elided
Sometimes you do not want to wait forever for a future to complete and need a way to limit the amount of time my program waits for a future to complete, returning a timeout if it takes too long. This case can occur in situations where we might want to ping a database service but do not want to wait forever to receive the result of ping.
The solution to this problem is to use akka after pattern which is a non-blocking approach to provide timeout to future.
According to Akka documentation, after pattern will return a future with success or failure according to the value specified after the duration specified in after pattern.
The firstCompletedOf function takes a list of futures as an argument and returns a new future which gets completed first from the list of futures provided.
So in the above code,
actualFuture is the future which contains actual processing. delayedFuture will get executed first i.e. fail after 200 ms with IllegalStateException. Therefore, timeoutFuture will be a future of the result of delayed as actualFuture could not be completed within the expected time.
The above approach does not interrupt the processing of the actual future operations. It only specifies that the operation was not completed within the duration specified in the delayedFuture. The future thread of actual business logic will be running and occupying background threads. So according to different use cases, one must use this approach as this can result in the duplicate result of the future operations which might not be the intended purpose. But the above usage involves Akka which is a heavy dependency which one might not want to use.
Hope you found this blog helpful and interesting.
Thanks for reading..!! 🙂