Kill or timeout a Future in Scala 2.10 - scala

Hi,
I'm using Scala 2.10 with the new futures library and I'm trying to write some code to test an infinite loop. I use a scala.concurrent.Future to run the code with the loop in a separate thread. I would then like to wait a little while to do some testing and then kill off the separate thread/future. I have looked at Await.result but that doesn't actually kill the future. Is there any way to timeout or kill the new Scala 2.10 futures?
I would prefer not having to add external dependencies such as Akka just for this simple part.

Do not try it at home.
import scala.concurrent._
import scala.concurrent.duration._
class MyCustomExecutionContext extends AnyRef with ExecutionContext {
import ExecutionContext.Implicits.global
#volatile var lastThread: Option[Thread] = None
override def execute(runnable: Runnable): Unit = {
ExecutionContext.Implicits.global.execute(new Runnable() {
override def run() {
lastThread = Some(Thread.currentThread)
runnable.run()
}
})
}
override def reportFailure(t: Throwable): Unit = ???
}
implicit val exec = new MyCustomExecutionContext()
val f = future[Int]{ do{}while(true); 1 }
try {
Await.result(f, 10 seconds) // 100% cpu here
} catch {
case e: TimeoutException =>
println("Stopping...")
exec.lastThread.getOrElse(throw new RuntimeException("Not started"))
.stop() // 0% cpu here
}

No - you will have to add a flag that your loop checks. If the flag is set, stop the loop. Make sure the flag is at least volatile.
See Java Concurrency in Practice, p 135-137.

I had a similar problem and wrote the following nonblocking future op:
class TerminationToken(var isTerminated: Boolean)
object TerminationToken { def apply() = new TerminationToken(false) }
implicit class FutureOps[T](future: Future[Option[T]]) {
def terminate(timeout: FiniteDuration, token: TerminationToken): Future[Option[T]] = {
val timeoutFuture = after[Option[T]](timeout, using = context.system.scheduler) {
Future[Option[T]] { token.isTerminated = true; None } }
Future.firstCompletedOf[Option[T]](Seq (future recover { case _ => None }, timeoutFuture))
}
}
Then just create a future that returns an option, and use .terminate(timeout, token) on it

Related

How to wrap a library async method with a threadsafe async wrapper in scala?

I'm working with a library that has a method that looks something like this.
trait LibraryDependency {
/**
* This method if called while previous future is not resolved will return a failed future
* #return
*/
def foo(): Future[Boolean]
}
Here the method foo() will return a failed future if there is a previous future that was returned by foo() that has not yet completed. Since I cannot modify the library's implementation of the trait, I am trying to wrap it with my own wrapper that provides the behaviour I need.
The behaviour I need is that if there are concurrent calls to foo(), then the other futures will also block until the first future is resolved. I tried to do something like this.
class ThreadSafeLibraryWrapper(delegate: LibraryDependency) extends LibraryDependency {
private val lock: Object = new Object
private implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
/**
* This one will block the other concurrent calls to foo()
* #return
*/
override def foo(): Future[Boolean] = {
val promise = Promise[Boolean]()
lock.synchronized {
val result = delegate.foo()
promise.completeWith(result)
result.onComplete { _ =>
lock.notify()
}
lock.wait()
}
promise.future
}
}
I'm running into the following issue, I'm not sure how to block the thread that is calling this method, and complete the original future, and I get IllegalMonitorStateException.
EDIT: I've solved this by using Await
class ThreadSafeLibraryWrapper(delegate: LibraryDependency) extends LibraryDependency {
private val lock: Object = new Object
private implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
/**
* This one will block the other concurrent calls to foo()
* #return
*/
override def foo(): Future[Boolean] = Future {
lock.synchronized {
Await.result(delegate.foo(), Duration.Inf)
}
}
}
I'm still not sure how to do this by avoiding Await.
If I correctly understood your question, your dependency can run on Future at time, so you would like to have wrapper which will limit access to foo method so to avoid returning failed future. If so, this looks like you need to en-queue next invocations until previous one will complete.
Well, I did some prototyping and I hope it helps:
import java.time.LocalTime.now
import scala.collection.immutable.Queue
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.util.{Failure, Success, Try}
object Concurrency {
trait LibraryDependency {
/**
* This method if called while previous future is not resolved will return a failed future
* #return
*/
def foo(): Future[Boolean]
}
class DummyLibraryDependency(implicit ec: ExecutionContext) extends LibraryDependency {
override def foo(): Future[Boolean] = {
Future {
println(s"${now()} - started dependency execution")
Thread.sleep(1000)
println(s"${now()} - finished dependency execution")
true
}
}
}
class SafeLibraryDependency(delegate: LibraryDependency)(implicit ec: ExecutionContext) {
private type OnComplete = Try[Boolean] => Unit
private var currentlyRunning: Option[Future[Boolean]] = None
private var queue: Queue[Promise[Boolean]] = Queue[Promise[Boolean]]()
def foo: Future[Boolean] = {
this.synchronized {
currentlyRunning.fold(startDelegateTask(onRunningComplete))(_ => enqueueNextTask())
}
}
private def enqueueNextTask(): Future[Boolean] = {
val promise = Promise[Boolean]()
queue = queue enqueue promise
promise.future
}
private def onRunningComplete(result: Try[Boolean]): Unit = {
this.synchronized {
currentlyRunning = None
if(queue.nonEmpty) {
val (promise, newQueue) = queue.dequeue
queue = newQueue
startDelegateTask { result =>
promise.complete(result)
onRunningComplete(result)
}
}
}
}
private def startDelegateTask(f: OnComplete): Future[Boolean] = {
val task = delegate.foo()
task.onComplete(f)
currentlyRunning = Some(task)
task
}
}
def main(args: Array[String]): Unit = {
import scala.concurrent.ExecutionContext.Implicits.global
val dummyLibraryDependency = new DummyLibraryDependency
val safeLibraryDependency = new SafeLibraryDependency(dummyLibraryDependency)
safeLibraryDependency.foo.onComplete(result => println(s"${now()} - #1 complete with result: $result"))
safeLibraryDependency.foo.onComplete(result => println(s"${now()} - #2 complete with result: $result"))
safeLibraryDependency.foo.onComplete(result => println(s"${now()} - #3 complete with result: $result"))
Thread.sleep(5000)
println("Done")
}
}
So SafeLibraryDependency - this is the wrapper, which limit's invocations to single running Future at time.
On my machine output was next:
19:30:43.666 - started dependency execution
19:30:44.679 - finished dependency execution
19:30:44.681 - started dependency execution
19:30:44.679 - #1 complete with result: Success(true)
19:30:45.681 - finished dependency execution
19:30:45.681 - started dependency execution
19:30:45.681 - #2 complete with result: Success(true)
19:30:46.682 - finished dependency execution
19:30:46.682 - #3 complete with result: Success(true)
Done
Hope this helps you!

Async before and after for creating and dropping scala slick tables in scalatest

I'm trying to figure out a way to have async before and after statements where the next test cases aren't run until the completion of the action inside of the test case. In my case, it is the creating and dropping a table inside of a database
val table = TableQuery[BlockHeaderTable]
val dbConfig: DatabaseConfig[PostgresDriver] = DatabaseConfig.forConfig("databaseUrl")
val database: Database = dbConfig.db
before {
//Awaits need to be used to make sure this is fully executed before the next test case starts
//TODO: Figure out a way to make this asynchronous
Await.result(database.run(table.schema.create), 10.seconds)
}
"BlockHeaderDAO" must "store a blockheader in the database, then read it from the database" in {
//...
}
it must "delete a block header in the database" in {
//...
}
after {
//Awaits need to be used to make sure this is fully executed before the next test case starts
//TODO: Figure out a way to make this asynchronous
Await.result(database.run(table.schema.drop),10.seconds)
}
Is there a simple way I can remove these Await calls inside of my before and after functions?
Unfortunately, #Jeffrey Chung's solution hanged for me (since futureValue actually awaits internally). This is what I ended up doing:
import org.scalatest.{AsyncFreeSpec, FutureOutcome}
import scala.concurrent.Future
class TestTest extends AsyncFreeSpec /* Could be any AsyncSpec. */ {
// Do whatever setup you need here.
def setup(): Future[_] = ???
// Cleanup whatever you need here.
def tearDown(): Future[_] = ???
override def withFixture(test: NoArgAsyncTest) = new FutureOutcome(for {
_ <- setup()
result <- super.withFixture(test).toFuture
_ <- tearDown()
} yield result)
}
The following is the testing approach that Dennis Vriend takes in his slick-3.2.0-test project.
First, define a dropCreateSchema method. This method attempts to create a table; if that attempt fails (because, for example, the table already exists), it drops, then creates, the table:
def dropCreateSchema: Future[Unit] = {
val schema = BlockHeaderTable.schema
db.run(schema.create)
.recoverWith {
case t: Throwable =>
db.run(DBIO.seq(schema.drop, schema.create))
}
}
Second, define a createEntries method that populates the table with some sample data for use in each test case:
def createEntries: Future[Unit] = {
val setup = DBIO.seq(
// insert some rows
BlockHeaderTable ++= Seq(
BlockHeaderTableRow(/* ... */),
// ...
)
).transactionally
db.run(setup)
}
Third, define an initialize method that calls the above two methods sequentially:
def initialize: Future[Unit] = for {
_ <- dropCreateSchema
_ <- createEntries
} yield ()
In the test class, mix in the ScalaFutures trait. For example:
class TestSpec extends FlatSpec
with Matchers
with ScalaFutures
with BeforeAndAfterAll
with BeforeAndAfterEach {
// ...
}
Also in the test class, define an implicit conversion from a Future to a Try, and override the beforeEach method to call initialize:
implicit val timeout: Timeout = 10.seconds
implicit class PimpedFuture[T](self: Future[T]) {
def toTry: Try[T] = Try(self.futureValue)
}
override protected def beforeEach(): Unit = {
blockHeaderRepo.initialize // in this example, initialize is defined in a repo class
.toTry recover {
case t: Throwable =>
log.error("Could not initialize the database", t)
} should be a 'success
}
override protected def afterAll(): Unit = {
db.close()
}
With the above pieces in place, there is no need for Await.
You can simplify #Jeffrey Chung
A simplified dropCreateSchema method:
def dropCreateSchema: Future[Unit] = {
val schema = users.schema
db.run(DBIO.seq(schema.dropIfExists, schema.create))
}
Also in the test class, I simplified beforeEach method that calls initialize. I removed an implicit conversion from a Future to a Try, and use onComplete callback:
override protected def beforeEach(): Unit = {
initialize.onComplete(f =>
f recover {
case t: Throwable =>
log.error("Could not initialize the database", t)
} should be a 'success)
}
override protected def afterAll(): Unit = {
db.close()
}

What is the simplest way to timeout in Scala?

There are many questions on SO that combine Futures with Timeout. To be honest, I haven't completely understood how to use them. But it seems I have stumbled upon a problem where I will have to (or maybe not).
I want to throw a TimeoutException if a statement takes more than say 1 minute.To be more clear, currently, this statement tries to get a response from a server but does not throw if the server is not setup. It currently looks like this:
//proper import of exceptions
case class ServerException(exception: Throwable) extends Exception(exception)
//Code that instantiates client and post
val response = try {
client.execute(post)
} catch {
case e#(_: IOException | _: ClientProtocolException) => throw new ServerException(e)
}
To mitigate this problem, I want to introduce a timeout. How do I introduce timeout to this statement such that it throws if no response is got within one minute, else it instantiates response and the program continues as it is?
It's not available in scala Futures. You can switch to scalaz Task - it's a bit different abstraction for async/delayed computations. You can read awesome documentation for it here: http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/
import java.util.concurrent.Executors
import scalaz.concurrent.Task
import scala.concurrent.duration._
implicit val scheduledThreadPool =
Executors.newScheduledThreadPool(5)
def executeRequest(req: Request): Task[Response] = ???
val withTimeOut: Task[Response] =
executeRequest(req).timed(1.minute)
Update
Btw you can easily transform your Future to Task, for example it Future is coming from 3rd party lib
object Future2Task {
implicit class Transformer[+T](fut: => Future[T]) {
def toTask(implicit ec: scala.concurrent.ExecutionContext): Task[T] = {
import scala.util.{Failure, Success}
import scalaz.syntax.either._
Task.async {
register =>
fut.onComplete {
case Success(v) => register(v.right)
case Failure(ex) => register(ex.left)
}
}
}
}
}
Timeouts are usually implemented by having an asynchronous timer act as the timeout signal and completing the future in question whenever it or the timer completes.
I believe Akka has a such a timer, but it's pretty simple to roll your own:
object ConcurrencyUtil {
// creates a Future that will complete after a specified duration
object Delay {
def apply(d: Duration): Future[Unit] = {
val p = Promise[Unit]()
val t = new Timer
t.schedule(new TimerTask {
override def run(): Unit = p.success()
}, d.toMillis)
p.future
}
}
implicit class FutureExtensions[T](future: Future[T]) {
def timeout(timeout: Duration) = Future.firstCompletedOf(Seq(
Delay(timeout).map(_ => throw new TimeoutException()),
future
))
}
}
Now you can compose timeout with your future like this:
import ConcurrencyUtil._
val f = someTaskReturningAFuture.timeout(1.minute)
What is now if the task has not completed within 1 minute, the delay will fire, get mapped to throwing a TimeoutException and complete the future f as failed.
Note: This does not address cancellation, i.e. the other future, while no longer being listened for will continue to exist and if it's executing something, continue to execute.

How to communicate between threads in Scala?

I have a class with some methods in Scala, each method has an execution time, for example methodA takes 10 seconds and methodB takes 5 seconds. and each method calls asynchronously.when I call methodB, it should cancel the thread that is running another methods. I first call methodA, and 2 seconds later I call methodB. What is the best solution for this problem?
def methodA()={
async{
// a job that takes 10 seconds
}
}
def methodB()={
async{
// other methods should stop their job
// a job that takes 5 second
}
}
def async[T](fn: => Unit): Unit = scala.actors.Actor.actor {
fn
}
.....
methodA()
methodB()
Here is an idea, based on the assumption that your method is actively checking whether it should still run or cancel:
import concurrent.{ExecutionContext, Future, Promise, blocking, future, promise}
case class Cancelled() extends RuntimeException
object Job {
def apply[A](fun: (() => Boolean) => A)(implicit ctx: ExecutionContext): Job[A] =
new Job[A] {
private val p = promise[A]
def result = p.future
def cancel(): Unit = p.tryFailure(Cancelled())
p tryCompleteWith future {
fun(() => !p.isCompleted)
}
}
}
trait Job[A] {
def result: Future[A]
def cancel(): Unit
}
So Job embodies a future along with a cancel() method. Your example could be similar to this:
import ExecutionContext.Implicits.global
val a = Job { active =>
for (i <- 1 to 100 if active()) {
blocking {
Thread.sleep(1000) // doing actual heavy work here
println(s"A $i")
}
}
}
val b = Job { active =>
for (i <- 1 to 20 if active()) {
blocking {
Thread.sleep(1000) // doing actual heavy work here
println(s"B $i")
}
}
println("Goodbye A...")
a.cancel()
}
I have also seen a rather harsh variant that calls Thread.interrupt.

Scala Futures - built in timeout?

there is an aspect of futures that I do not exactly understand from the official tutorial ref. http://docs.scala-lang.org/overviews/core/futures.html
Do futures in scala have a built in time-out mechanism of some kind? Let's say the example below was a 5 gigabyte text file... does the implied scope of "Implicits.global" eventually cause onFailure to fire in a non-blocking way or can that be defined? And without a default time-out of some kind, wouldn't that imply it's possible neither success nor failure would ever fire?
import scala.concurrent._
import ExecutionContext.Implicits.global
val firstOccurence: Future[Int] = future {
val source = scala.io.Source.fromFile("myText.txt")
source.toSeq.indexOfSlice("myKeyword")
}
firstOccurence onSuccess {
case idx => println("The keyword first appears at position: " + idx)
}
firstOccurence onFailure {
case t => println("Could not process file: " + t.getMessage)
}
You only get timeout behavior when you use blocking to get the results of the Future. If you want to use the non-blocking callbacks onComplete, onSuccess or onFailure, then you would have to roll your own timeout handling. Akka has built in timeout handling for request/response (?) messaging between actors, but not sure if you want to start using Akka. FWIW, in Akka, for timeout handling, they compose two Futures together via Future.firstCompletedOf, one which represents the actual async task and one that represents the timeout. If the timeout timer (via a HashedWheelTimer) pops first, you get a failure on the async callback.
A very simplified example of rolling your own might go something like this. First, an object for scheduling timeouts:
import org.jboss.netty.util.{HashedWheelTimer, TimerTask, Timeout}
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
import scala.concurrent.Promise
import java.util.concurrent.TimeoutException
object TimeoutScheduler{
val timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS)
def scheduleTimeout(promise:Promise[_], after:Duration) = {
timer.newTimeout(new TimerTask{
def run(timeout:Timeout){
promise.failure(new TimeoutException("Operation timed out after " + after.toMillis + " millis"))
}
}, after.toNanos, TimeUnit.NANOSECONDS)
}
}
Then a function to take a Future and add timeout behavior to it:
import scala.concurrent.{Future, ExecutionContext, Promise}
import scala.concurrent.duration.Duration
def withTimeout[T](fut:Future[T])(implicit ec:ExecutionContext, after:Duration) = {
val prom = Promise[T]()
val timeout = TimeoutScheduler.scheduleTimeout(prom, after)
val combinedFut = Future.firstCompletedOf(List(fut, prom.future))
fut onComplete{case result => timeout.cancel()}
combinedFut
}
Note that the HashedWheelTimer I am using here is from Netty.
All of these answers require additional dependencies. I decided to write a version using java.util.Timer which is an efficient way to run a function in the future, in this case to trigger a timeout.
Blog post with more details here
Using this with Scala's Promise, we can make a Future with timeout as follows:
package justinhj.concurrency
import java.util.concurrent.TimeoutException
import java.util.{Timer, TimerTask}
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.language.postfixOps
object FutureUtil {
// All Future's that use futureWithTimeout will use the same Timer object
// it is thread safe and scales to thousands of active timers
// The true parameter ensures that timeout timers are daemon threads and do not stop
// the program from shutting down
val timer: Timer = new Timer(true)
/**
* Returns the result of the provided future within the given time or a timeout exception, whichever is first
* This uses Java Timer which runs a single thread to handle all futureWithTimeouts and does not block like a
* Thread.sleep would
* #param future Caller passes a future to execute
* #param timeout Time before we return a Timeout exception instead of future's outcome
* #return Future[T]
*/
def futureWithTimeout[T](future : Future[T], timeout : FiniteDuration)(implicit ec: ExecutionContext): Future[T] = {
// Promise will be fulfilled with either the callers Future or the timer task if it times out
val p = Promise[T]
// and a Timer task to handle timing out
val timerTask = new TimerTask() {
def run() : Unit = {
p.tryFailure(new TimeoutException())
}
}
// Set the timeout to check in the future
timer.schedule(timerTask, timeout.toMillis)
future.map {
a =>
if(p.trySuccess(a)) {
timerTask.cancel()
}
}
.recover {
case e: Exception =>
if(p.tryFailure(e)) {
timerTask.cancel()
}
}
p.future
}
}
I've just created a TimeoutFuture class for a coworker:
TimeoutFuture
package model
import scala.concurrent._
import scala.concurrent.duration._
import play.libs.Akka
import play.api.libs.concurrent.Execution.Implicits._
object TimeoutFuture {
def apply[A](timeout: FiniteDuration)(block: => A): Future[A] = {
val prom = promise[A]
// timeout logic
Akka.system.scheduler.scheduleOnce(timeout) {
prom tryFailure new java.util.concurrent.TimeoutException
}
// business logic
Future {
prom success block
}
prom.future
}
}
Usage
val future = TimeoutFuture(10 seconds) {
// do stuff here
}
future onComplete {
case Success(stuff) => // use "stuff"
case Failure(exception) => // catch exception (either TimeoutException or an exception inside the given block)
}
Notes:
Assumes Play! framework (but it's easy enough to adapt)
Every piece of code runs in the same ExecutionContext which may not be ideal.
Play framework contains Promise.timeout so you can write code like following
private def get(): Future[Option[Boolean]] = {
val timeoutFuture = Promise.timeout(None, Duration("1s"))
val mayBeHaveData = Future{
// do something
Some(true)
}
// if timeout occurred then None will be result of method
Future.firstCompletedOf(List(mayBeHaveData, timeoutFuture))
}
I'm quite surprise this is not standard in Scala. My versions is short and has no dependencies
import scala.concurrent.Future
sealed class TimeoutException extends RuntimeException
object FutureTimeout {
import scala.concurrent.ExecutionContext.Implicits.global
implicit class FutureTimeoutLike[T](f: Future[T]) {
def withTimeout(ms: Long): Future[T] = Future.firstCompletedOf(List(f, Future {
Thread.sleep(ms)
throw new TimeoutException
}))
lazy val withTimeout: Future[T] = withTimeout(2000) // default 2s timeout
}
}
Usage example
import FutureTimeout._
Future { /* do smth */ } withTimeout
If you want the writer (promise holder) to be the one who controls the timeout logic, use akka.pattern.after, in the following way:
val timeout = akka.pattern.after(10 seconds, system.scheduler)(Future.failed(new TimeoutException(s"timed out during...")))
Future.firstCompletedOf(Seq(promiseRef.future, timeout))
This way, if your promise completion logic never takes place, your caller's future will still be completed at some point with a failure.
You can specify the timeout when you wait on the future:
For scala.concurrent.Future, the result method lets you specify a timeout.
For scala.actors.Future, Futures.awaitAll lets you specify a timeout.
I do not think there is a timeout built-in the execution of a Future.
Nobody's mentioned akka-streams, yet. The flows have an easy completionTimeout method, and applying that on a single-source stream works like a Future.
But, akka-streams also does cancellation so it can actually end the source from running, i.e. it signals the timeout to the source.
Monix Task has timeout support
import monix.execution.Scheduler.Implicits.global
import monix.eval._
import scala.concurrent.duration._
import scala.concurrent.TimeoutException
val source = Task("Hello!").delayExecution(10.seconds)
// Triggers error if the source does not complete in 3 seconds after runOnComplete
val timedOut = source.timeout(3.seconds)
timedOut.runOnComplete(r => println(r))
//=> Failure(TimeoutException)
This version works without using any external timer (just Await.result)
import scala.concurrent._
import scala.concurrent.duration.FiniteDuration
object TimeoutFuture {
def apply[A](
timeout: FiniteDuration
)(block: => A)(implicit executor: ExecutionContext): Future[A] =
try {
Future { Await.result(Future { block }, timeout) }
} catch {
case _: TimeoutException => Future.failed(new TimeoutException(s"Timed out after ${timeout.toString}"))
}
}
I'm using this version (based on Play example above) which uses Akka system dispatcher:
object TimeoutFuture {
def apply[A](system: ActorSystem, timeout: FiniteDuration)(block: => A): Future[A] = {
implicit val executionContext = system.dispatcher
val prom = Promise[A]
// timeout logic
system.scheduler.scheduleOnce(timeout) {
prom tryFailure new java.util.concurrent.TimeoutException
}
// business logic
Future {
try {
prom success block
} catch {
case t: Throwable => prom tryFailure t
}
}
prom.future
}
}
The simplest way to specify timeout on Future IMO is scala's built in mechanism using scala.concurrent.Await.ready This will throw a TimeoutException if the Future takes longer than the specified timeout. Otherwise, it will return the Future itself.
Here is a simple contrived example
import scala.concurrent.ExecutionContext.Implicits._
import scala.concurrent.duration._
val f1: Future[Int] = Future {
Thread.sleep(1100)
5
}
val fDoesntTimeout: Future[Int] = Await.ready(f1, 2000 milliseconds)
val f: Future[Int] = Future {
Thread.sleep(1100)
5
}
val fTimesOut: Future[Int] = Await.ready(f, 100 milliseconds)
You can wait for a future to finish by making use of Await.
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
val meaningOfLife: Int = Await.result(Future(42), 1.nano)
println (meaningOfLife)
The above prints 42
You may need an implicit ExecutionContext available in which case, just add:
import scala.concurrent.ExecutionContext.Implicits.global
Another way to do it is to use Coeval from monix. This method does not work in all situations, and you can read all about it here.
The basic idea is that sometimes a future does not really take any time and is returning the result of a synchronous function call or value, so this future can be evaluated on the current thread. This is also useful for testing and mocking futures. Also you don't have to specify a timeout which is expected, but still nice to not have to worry about that.
You start by transforming the future into a Task and wrap that task in a Coeval then cross your fingers as you wait to see what you get. This is a very simple example to show how it works:
You need an implicit Scheduler to be able to use it:
import monix.execution.Scheduler.Implicits.global
Coeval(Task.fromFuture(Future (42)).runSyncStep).value() match {
case Right(v) => println(v)
case Left(task) => println("Task did not finish")
}
The above completes and prints 42 to the console.
Coeval(Task.fromFuture(Future {
scala.concurrent.blocking {
42
}
}).runSyncStep).value() match {
case Right(v) => println(v)
case Left(task) => println("Task did not finish")
}
This example prints Task did not finish:
You can simply run the future to completion without giving any timeout interval by setting the timeout to infinite as below:
**import scala.concurrent.duration._
Await.result(run(executionContext), Duration.Inf)**
run function can be as below :
def run(implicit ec: ExecutionContext) = {
val list = Seq(
Future { println("start 1"); Thread.sleep(1000); println("stop 1")},
Future { println("start 2"); Thread.sleep(2000); println("stop 2")},
Future { println("start 3"); Thread.sleep(3000); println("stop 3")},
Future { println("start 4"); Thread.sleep(4000); println("stop 4")},
Future { println("start 5"); Thread.sleep(5000); println("stop 5")}
)
Future.sequence(list)
}