Below is a simple program that awaits a cancellable future. The future should evaluate to wait 20 seconds. I'm trying to demonstrate the 5.second max time bound kicking in. However, the program seems to ignore the 5.second max time bound, and waits for 20 seconds. Does anyone know why this is? Thanks
import com.github.nscala_time.time.Imports.{DateTime, richReadableInstant, richReadableInterval}
import monix.eval.Task
import monix.execution.Scheduler
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Await
object TaskRunToFuture extends App {
def waitTwenty = {
val start = DateTime.now()
while ((start to DateTime.now()).millis < 20000) { /** do nothing */ }
}
val result = Await.result(Task.eval(waitTwenty).runToFuture, 5.seconds)
}
CodePudding user response:
From Monix's Design Summary:
doesn’t necessarily execute on another logical thread
In your case, you've defined a Task that doesn't inherently have any "async boundaries" that would force Monix to shift to another thread, so when you call runToFuture
it ends up executing waitTwenty
on the current thread. Thus, the task has already completed by the time the Future is actually returned, so Await.result
isn't actually called until the 20 seconds are up.
See Task#executeAsync
which inserts an async boundary before the task, e.g. Task.eval(waitTwenty).executeAsync.runToFuture
Normally this kind of thing isn't an issue since you generally don't want to call any of the run*
methods except in your application's main
; instead you'll compose everything in terms of Task
so your whole app is ultimately one big Task
that can be run, e.g. as a TaskApp
.
def waitTwenty = {
println("starting wait...")
Thread.sleep(20000)
println("done waiting!")
}
Await.result(Task.eval(waitTwenty).executeAsync.runToFuture, 5.seconds)
Outputs
waiting...
java.util.concurrent.TimeoutException: Future timed out after [5 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:248)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:261)
at monix.execution.CancelableFuture$Async.result(CancelableFuture.scala:371)
at scala.concurrent.Await$.$anonfun$result$1(package.scala:201)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:62)
at scala.concurrent.Await$.result(package.scala:124)
... 59 elided