Class/Object

monix.eval

Task

Related Docs: object Task | package eval

Permalink

sealed abstract class Task[+A] extends Serializable

Task represents a specification for a possibly lazy or asynchronous computation, which when executed will produce an A as a result, along with possible side-effects.

Compared with Future from Scala's standard library, Task does not represent a running computation or a value detached from time, as Task does not execute anything when working with its builders or operators and it does not submit any work into any thread-pool, the execution eventually taking place only after runAsync is called and not before that.

Note that Task is conservative in how it spawns logical threads. Transformations like map and flatMap for example will default to being executed on the logical thread on which the asynchronous computation was started. But one shouldn't make assumptions about how things will end up executed, as ultimately it is the implementation's job to decide on the best execution model. All you are guaranteed is asynchronous execution after executing runAsync.

Getting Started

To build a Task from a by-name parameters (thunks), we can use Task.eval or Task.apply:

val hello = Task.eval("Hello ")
val world = Task("World!")

Nothing gets executed yet, as Task is lazy, nothing executes until you trigger .runAsync on it.

To combine Task values we can use .map and .flatMap, which describe sequencing and this time it's in a very real sense because of the laziness involved:

val sayHello = hello
  .flatMap(h => world.map(w => h + w))
  .map(println)

This Task reference will trigger a side effect on evaluation, but not yet. To make the above print its message:

import monix.execution.CancelableFuture

val f: CancelableFuture[Unit] = sayHello.run()
//=> Hello World!

The returned type is a CancelableFuture which inherits from Scala's standard Future, a value that can be completed already or might be completed at some point in the future, once the running asynchronous process finishes. Such a future value can also be canceled, see below.

Laziness

The fact that Task is lazy whereas Future is not has real consequences. For example with Task you can do this:

def retryOnFailure[A](times: Int, source: Task[A]): Task[A] =
  source.onErrorRecoverWith { err =>
    // No more retries left? Re-throw error:
    if (times <= 0) Task.raiseError(err) else {
      // Recursive call, yes we can!
      retryOnFailure(times - 1, source)
        // Adding 500 ms delay for good measure
        .delayExecution(500)
    }
  }

Future being a strict value-wannabe means that the actual value gets "memoized" (means cached), however Task is basically a function that can be repeated for as many times as you want. Task can also do memoization of course:

task.memoize

The difference between this and just calling runAsync() is that memoize() still returns a Task and the actual memoization happens on the first runAsync() (with idempotency guarantees of course).

But here's something else that the Future data type cannot do:

task.memoizeOnSuccess

This keeps repeating the computation for as long as the result is a failure and caches it only on success. Yes we can!

Parallelism

Because of laziness, invoking Task.sequence will not work like it does for Future.sequence, the given Task values being evaluated one after another, in sequence, not in parallel. If you want parallelism, then you need to use Task.gather and thus be explicit about it.

This is great because it gives you the possibility of fine tuning the execution. For example, say you want to execute things in parallel, but with a maximum limit of 30 tasks being executed in parallel. One way of doing that is to process your list in batches:

// Some array of tasks, you come up with something good :-)
val list: Seq[Task[Int]] = ???

// Split our list in chunks of 30 items per chunk,
// this being the maximum parallelism allowed
val chunks = list.sliding(30, 30)

// Specify that each batch should process stuff in parallel
val batchedTasks = chunks.map(chunk => Task.gather(chunk))
// Sequence the batches
val allBatches = Task.sequence(batchedTasks)

// Flatten the result, within the context of Task
val all: Task[Seq[Int]] = allBatches.map(_.flatten)

Note that the built Task reference is just a specification at this point, or you can view it as a function, as nothing has executed yet, you need to call .runAsync explicitly.

Cancellation

The logic described by an Task task could be cancelable, depending on how the Task gets built.

CancelableFuture references can also be canceled, in case the described computation can be canceled. When describing Task tasks with Task.eval nothing can be cancelled, since there's nothing about a plain function that you can cancel, but we can build cancelable tasks with Task.async (alias Task.create):

import scala.concurrent.duration._

val delayedHello = Task.async { (scheduler, callback) =>
  val task = scheduler.scheduleOnce(1.second) {
    println("Delayed Hello!")
    // Signaling successful completion
    callback(Success(()))
  }

  Cancelable { () => {
    println("Cancelling!")
    task.cancel()
  }
}

The sample above prints a message with a delay, where the delay itself is scheduled with the injected Scheduler. The Scheduler is in fact an implicit parameter to runAsync().

This action can be cancelled, because it specifies cancellation logic. In case we have no cancelable logic to express, then it's OK if we returned a Cancelable.empty reference, in which case the resulting Task would not be cancelable.

But the Task we just described is cancelable, for one at the edge, due to runAsync returning Cancelable and CancelableFuture references:

// Triggering execution
val f: CancelableFuture[Unit] = delayedHello.runAsync

// If we change our mind before the timespan has passed:
f.cancel()

But also cancellation is described on Task as a pure action, which can be used for example in race conditions:

import scala.concurrent.duration._

val ta = Task(1)
  .delayExecution(4.seconds)
val tb = Task.raiseError(new TimeoutException)
  .delayExecution(4.seconds)

Task.racePair(ta, tb).flatMap {
  case Left((a, fiberB)) =>
    fiberB.cancel.map(_ => a)
  case Right((fiberA, b)) =>
    fiberA.cancel.map(_ => b)
}

The returned type in racePair is Fiber, which is a data type that's meant to wrap tasks linked to an active process and that can be canceled or joined.

Also, given a task, we can specify actions that need to be triggered in case of cancellation, see doOnCancel:

val task = Task.eval(println("Hello!")).executeAsync

task doOnCancel Task.eval {
  println("A cancellation attempt was made!")
}

Controlling cancellation can be achieved with cancelable and uncancelable.

The former activates auto-cancelable flatMap chains, whereas the later ensures that a task becomes uncancelable such that it gets executed as an atomic unit (either all or nothing).

Note on the ExecutionModel

Task is conservative in how it introduces async boundaries. Transformations like map and flatMap for example will default to being executed on the current call stack on which the asynchronous computation was started. But one shouldn't make assumptions about how things will end up executed, as ultimately it is the implementation's job to decide on the best execution model. All you are guaranteed (and can assume) is asynchronous execution after executing runAsync.

Currently the default ExecutionModel specifies batched execution by default and Task in its evaluation respects the injected ExecutionModel. If you want a different behavior, you need to execute the Task reference with a different scheduler.

Linear Supertypes
Serializable, Serializable, AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. Task
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Value Members

  1. final def !=(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0

    Permalink
    Definition Classes
    Any
  5. final def asyncBoundary(s: Scheduler): Task[A]

    Permalink

    Introduces an asynchronous boundary at the current stage in the asynchronous processing pipeline, making processing to jump on the given Scheduler (until the next async boundary).

    Introduces an asynchronous boundary at the current stage in the asynchronous processing pipeline, making processing to jump on the given Scheduler (until the next async boundary).

    Consider the following example:

    import monix.execution.Scheduler
    val io = Scheduler.io()
    
    val source = Task(1).executeOn(io).map(_ + 1)

    That task is being forced to execute on the io scheduler, including the map transformation that follows after executeOn. But what if we want to jump with the execution run-loop on another scheduler for the following transformations?

    Then we can do:

    import monix.execution.Scheduler.global
    
    source.asyncBoundary(global).map(_ + 2)

    In this sample, whatever gets evaluated by the source will happen on the io scheduler, however the asyncBoundary call will make all subsequent operations to happen on the specified global scheduler.

    s

    is the scheduler triggering the asynchronous boundary

  6. final def asyncBoundary: Task[A]

    Permalink

    Introduces an asynchronous boundary at the current stage in the asynchronous processing pipeline.

    Introduces an asynchronous boundary at the current stage in the asynchronous processing pipeline.

    Consider the following example:

    import monix.execution.Scheduler
    val io = Scheduler.io()
    
    val source = Task(1).executeOn(io).map(_ + 1)

    That task is being forced to execute on the io scheduler, including the map transformation that follows after executeOn. But what if we want to jump with the execution run-loop on the default scheduler for the following transformations?

    Then we can do:

    source.asyncBoundary.map(_ + 2)

    In this sample, whatever gets evaluated by the source will happen on the io scheduler, however the asyncBoundary call will make all subsequent operations to happen on the default scheduler.

  7. final def attempt: Task[Either[Throwable, A]]

    Permalink

    Creates a new Task that will expose any triggered error from the source.

  8. final def bracket[B](use: (A) ⇒ Task[B])(release: (A) ⇒ Task[Unit]): Task[B]

    Permalink

    Returns a task that treats the source task as the acquisition of a resource, which is then exploited by the use function and then released.

    Returns a task that treats the source task as the acquisition of a resource, which is then exploited by the use function and then released.

    The bracket operation is the equivalent of the try {} catch {} finally {} statements from mainstream languages.

    The bracket operation installs the necessary exception handler to release the resource in the event of an exception being raised during the computation, or in case of cancellation.

    If an exception is raised, then bracket will re-raise the exception after performing the release. If the resulting task gets cancelled, then bracket will still perform the release, but the yielded task will be non-terminating (equivalent with Task.never).

    Example:

    import java.io._
    
    def readFile(file: File): Task[String] = {
      // Opening a file handle for reading text
      val acquire = Task.eval(new BufferedReader(
        new InputStreamReader(new FileInputStream(file), "utf-8")
      ))
    
      acquire.bracket { in =>
        // Usage part
        Task.eval {
          // Yes, ugly Java, non-FP loop;
          // side-effects are suspended though
          var line: String = null
          val buff = new StringBuilder()
          do {
            line = in.readLine()
            if (line != null) buff.append(line)
          } while (line != null)
          buff.toString()
        }
      } { in =>
        // The release part
        Task.eval(in.close())
      }
    }

    Note that in case of cancellation the underlying implementation cannot guarantee that the computation described by use doesn't end up executed concurrently with the computation from release. In the example above that ugly Java loop might end up reading from a BufferedReader that is already closed due to the task being cancelled, thus triggering an error in the background with nowhere to go but in Scheduler.reportFailure.

    In this particular example, given that we are just reading from a file, it doesn't matter. But in other cases it might matter, as concurrency on top of the JVM when dealing with I/O might lead to corrupted data.

    For those cases you might want to do synchronization (e.g. usage of locks and semaphores) and you might want to use bracketE, the version that allows you to differentiate between normal termination and cancellation.

    NOTE on error handling: one big difference versus try {} finally {} is that, in case both the release function and the use function throws, the error raised by use gets signaled and the error raised by release gets reported with System.err for Coeval or with Scheduler.reportFailure for Task.

    For example:

    Task("resource").bracket { _ =>
      // use
      Task.raiseError(new RuntimeException("Foo"))
    } { _ =>
      // release
      Task.raiseError(new RuntimeException("Bar"))
    }

    In this case the error signaled downstream is "Foo", while the "Bar" error gets reported. This is consistent with the behavior of Haskell's bracket operation and NOT with try {} finally {} from Scala, Java or JavaScript.

    use

    is a function that evaluates the resource yielded by the source, yielding a result that will get generated by the task returned by this bracket function

    release

    is a function that gets called after use terminates, either normally or in error, or if it gets cancelled, receiving as input the resource that needs to be released

    See also

    bracketE

  9. final def bracketE[B](use: (A) ⇒ Task[B])(release: (A, Either[Option[Throwable], B]) ⇒ Task[Unit]): Task[B]

    Permalink

    Returns a task that treats the source task as the acquisition of a resource, which is then exploited by the use function and then released, with the possibility of distinguishing between normal termination and cancellation, such that an appropriate release of resources can be executed.

    Returns a task that treats the source task as the acquisition of a resource, which is then exploited by the use function and then released, with the possibility of distinguishing between normal termination and cancellation, such that an appropriate release of resources can be executed.

    The bracketE operation is the equivalent of try {} catch {} finally {} statements from mainstream languages.

    The bracketE operation installs the necessary exception handler to release the resource in the event of an exception being raised during the computation, or in case of cancellation.

    In comparison with the simpler bracket version, this one allows the caller to differentiate between normal termination and cancellation.

    The release function receives as input:

    • Left(None) in case of cancellation
    • Left(Some(error)) in case use terminated with an error
    • Right(b) in case of success

    NOTE on error handling: one big difference versus try {} finally {} is that, in case both the release function and the use function throws, the error raised by use gets signaled and the error raised by release gets reported with System.err for Coeval or with Scheduler.reportFailure for Task.

    For example:

    Task("resource").bracket { _ =>
      // use
      Task.raiseError(new RuntimeException("Foo"))
    } { _ =>
      // release
      Task.raiseError(new RuntimeException("Bar"))
    }

    In this case the error signaled downstream is "Foo", while the "Bar" error gets reported. This is consistent with the behavior of Haskell's bracket operation and NOT with try {} finally {} from Scala, Java or JavaScript.

    use

    is a function that evaluates the resource yielded by the source, yielding a result that will get generated by this function on evaluation

    release

    is a function that gets called after use terminates, either normally or in error, or if it gets cancelled, receiving as input the resource that needs that needs release, along with the result of use (cancellation, error or successful result)

    See also

    bracket

  10. def cancelable: Task[A]

    Permalink

    Returns a new task that is cancelable.

    Returns a new task that is cancelable.

    Normally Monix Tasks have these characteristics:

    • flatMap chains are not cancelable by default
    • when creating async tasks the user has to specify explicit cancellation logic

    This operation returns a task that has Task.Options.autoCancelableRunLoops enabled upon evaluation, thus being equivalent with:

    task.executeWithOptions(_.enableAutoCancelableRunLoops)

    What this does is two-fold:

    • flatMap chains become cancelable on async boundaries, which works in combination with BatchedExecution that's enabled by default (injected by Scheduler, but can also be changed with executeWithModel)
    • even if the source task cannot be cancelled, upon completion the result is not allowed to be streamed and the continuation is not allowed to execute

    For example this is a function that calculates the n-th Fibonacci element:

    def fib(n: Int): Task[Long] = {
      def loop(n: Int, a: Long, b: Long): Task[Long] =
        Task.suspend {
          if (n > 0)
            loop(n - 1, b, a + b)
          else
            Task.now(a)
        }
    
      loop(n, 0, 1).cancelable
    }

    Normally this isn't cancelable and it might take a long time, but by calling cancelable on the result, we ensure that when cancellation is observed, at async boundaries, the loop will stop with the task becoming a non-terminating one.

    This operation represents the opposite of uncancelable. And note that it works even for tasks that are uncancelable / atomic, because it blocks the rest of the flatMap loop from executing, functioning like a sort of cancellation boundary:

    Task(println("Hello ..."))
      .cancelable
      .flatMap(_ => Task.eval(println("World!")))

    Normally Task.apply does not yield a cancelable task, but by applying the cancelable transformation to it, the println will execute, but not the subsequent flatMap operation.

  11. def clone(): AnyRef

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  12. final def coeval(implicit s: Scheduler): Coeval[Either[CancelableFuture[A], A]]

    Permalink

    Transforms a Task into a Coeval that tries to execute the source synchronously, returning either Right(value) in case a value is available immediately, or Left(future) in case we have an asynchronous boundary or an error.

  13. final def delayExecution(timespan: FiniteDuration): Task[A]

    Permalink

    Returns a task that waits for the specified timespan before executing and mirroring the result of the source.

    Returns a task that waits for the specified timespan before executing and mirroring the result of the source.

    In this example we're printing to standard output, but before doing that we're introducing a 3 seconds delay:

    Task(println("Hello!"))
      .delayExecution(3.seconds)

    This operation is also equivalent with:

    Task.sleep(timespan).flatMap(_ => task)

    See Task.sleep for the operation that describes the effect and Task.delayResult for the version that evaluates the task on time, but delays the signaling of the result.

    timespan

    is the time span to wait before triggering the evaluation of the task

  14. final def delayResult(timespan: FiniteDuration): Task[A]

    Permalink

    Returns a task that executes the source immediately on runAsync, but before emitting the onSuccess result for the specified duration.

    Returns a task that executes the source immediately on runAsync, but before emitting the onSuccess result for the specified duration.

    Note that if an error happens, then it is streamed immediately with no delay.

    See delayExecution for delaying the evaluation of the task with the specified duration. The delayResult operation is effectively equivalent with:

    task.flatMap(a => Task.now(a).delayExecution(timespan))

    Or if we are to use the Task.sleep describing just the effect, this operation is equivalent with:

    task.flatMap(a => Task.sleep(timespan).map(_ => a))

    Thus in this example 3 seconds will pass before the result is being generated by the source, plus another 5 seconds before it is finally emitted:

    Task.eval(1 + 1)
      .delayExecution(3.seconds)
      .delayResult(5.seconds)
    timespan

    is the time span to sleep before signaling the result, but after the evaluation of the source

  15. final def dematerialize[B](implicit ev: <:<[A, Try[B]]): Task[B]

    Permalink

    Dematerializes the source's result from a Try.

  16. final def doOnCancel(callback: Task[Unit]): Task[A]

    Permalink

    Returns a new Task that will mirror the source, but that will execute the given callback if the task gets canceled before completion.

    Returns a new Task that will mirror the source, but that will execute the given callback if the task gets canceled before completion.

    This only works for premature cancellation. See doOnFinish for triggering callbacks when the source finishes.

    callback

    is the callback to execute if the task gets canceled prematurely

  17. final def doOnFinish(f: (Option[Throwable]) ⇒ Task[Unit]): Task[A]

    Permalink

    Returns a new Task in which f is scheduled to be run on completion.

    Returns a new Task in which f is scheduled to be run on completion. This would typically be used to release any resources acquired by this Task.

    The returned Task completes when both the source and the task returned by f complete.

    NOTE: The given function is only called when the task is complete. However the function does not get called if the task gets canceled. Cancellation is a process that's concurrent with the execution of a task and hence needs special handling.

    See doOnCancel for specifying a callback to call on canceling a task.

  18. final def eq(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  19. def equals(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  20. final def executeAsync: Task[A]

    Permalink

    Mirrors the given source Task, but upon execution ensure that evaluation forks into a separate (logical) thread.

    Mirrors the given source Task, but upon execution ensure that evaluation forks into a separate (logical) thread.

    The Scheduler used will be the one that is used to start the run-loop in .runAsync.

    This operation is equivalent with:

    Task.shift.flatMap(_ => task)
    
    // ... or ...
    
    import cats.syntax.all._
    
    Task.shift.followedBy(task)

    The Scheduler used for scheduling the async boundary will be the default, meaning the one used to start the run-loop in runAsync.

  21. final def executeOn(s: Scheduler, forceAsync: Boolean = true): Task[A]

    Permalink

    Overrides the default Scheduler, possibly forcing an asynchronous boundary before execution (if forceAsync is set to true, the default).

    Overrides the default Scheduler, possibly forcing an asynchronous boundary before execution (if forceAsync is set to true, the default).

    When a Task is executed with .runAsync, it needs a Scheduler, which is going to be injected in all asynchronous tasks processed within the flatMap chain, a Scheduler that is used to manage asynchronous boundaries and delayed execution.

    This scheduler passed in runAsync is said to be the "default" and executeOn overrides that default.

    import monix.execution.Scheduler
    import java.io.{BufferedReader, FileInputStream, InputStreamReader}
    
    /** Reads the contents of a file using blocking I/O. */
    def readFile(path: String): Task[String] = Task.eval {
      val in = new BufferedReader(
        new InputStreamReader(new FileInputStream(path), "utf-8"))
    
      val buffer = new StringBuffer()
      var line: String = null
      do {
        line = in.readLine()
        if (line != null) buffer.append(line)
      } while (line != null)
    
      buffer.toString
    }
    
    // Building a Scheduler meant for blocking I/O
    val io = Scheduler.io()
    
    // Building the Task reference, specifying that `io` should be
    // injected as the Scheduler for managing async boundaries
    readFile("path/to/file").executeOn(io, forceAsync = true)

    In this example we are using Task.eval, which executes the given thunk immediately (on the current thread and call stack).

    By calling executeOn(io), we are ensuring that the used Scheduler (injected in async tasks by means of Task.Context) will be io, a Scheduler that we intend to use for blocking I/O actions. And we are also forcing an asynchronous boundary right before execution, by passing the forceAsync parameter as true (which happens to be the default value).

    Thus, for our described function that reads files using Java's blocking I/O APIs, we are ensuring that execution is entirely managed by an io scheduler, executing that logic on a thread pool meant for blocking I/O actions.

    Note that in case forceAsync = false, then the invocation will not introduce any async boundaries of its own and will not ensure that execution will actually happen on the given Scheduler, that depending of the implementation of the Task. For example:

    Task.eval("Hello, " + "World!")
      .executeOn(io, forceAsync = false)

    The evaluation of this task will probably happen immediately (depending on the configured ExecutionModel) and the given scheduler will probably not be used at all.

    However in case we would use Task.apply, which ensures that execution of the provided thunk will be async, then by using executeOn we'll indeed get a logical fork on the io scheduler:

    Task("Hello, " + "World!")
      .executeOn(io, forceAsync = false)

    Also note that overriding the "default" scheduler can only happen once, because it's only the "default" that can be overridden.

    Something like this won't have the desired effect:

    val io1 = Scheduler.io()
    val io2 = Scheduler.io()
    
    task.executeOn(io1).executeOn(io2)

    In this example the implementation of task will receive the reference to io1 and will use it on evaluation, while the second invocation of executeOn will create an unnecessary async boundary (if forceAsync = true) or be basically a costly no-op. This might be confusing but consider the equivalence to these functions:

    import scala.concurrent.ExecutionContext
    
    val io1 = Scheduler.io()
    val io2 = Scheduler.io()
    
    def sayHello(ec: ExecutionContext): Unit =
      ec.execute(new Runnable {
        def run() = println("Hello!")
      })
    
    def sayHello2(ec: ExecutionContext): Unit =
      // Overriding the default `ec`!
      sayHello(io1)
    
    def sayHello3(ec: ExecutionContext): Unit =
      // Overriding the default no longer has the desired effect
      // because sayHello2 is ignoring it!
      sayHello2(io2)
    s

    is the Scheduler to use for overriding the default scheduler and for forcing an asynchronous boundary if forceAsync is true

    forceAsync

    indicates whether an asynchronous boundary should be forced right before the evaluation of the Task, managed by the provided Scheduler

    returns

    a new Task that mirrors the source on evaluation, but that uses the provided scheduler for overriding the default and possibly force an extra asynchronous boundary on execution

  22. final def executeWithModel(em: ExecutionModel): Task[A]

    Permalink

    Returns a new task that will execute the source with a different ExecutionModel.

    Returns a new task that will execute the source with a different ExecutionModel.

    This allows fine-tuning the options injected by the scheduler locally. Example:

    import monix.execution.ExecutionModel.AlwaysAsyncExecution
    task.executeWithModel(AlwaysAsyncExecution)
    em

    is the ExecutionModel with which the source will get evaluated on runAsync

  23. final def executeWithOptions(f: (Options) ⇒ Options): Task[A]

    Permalink

    Returns a new task that will execute the source with a different set of Options.

    Returns a new task that will execute the source with a different set of Options.

    This allows fine-tuning the default options. Example:

    task.executeWithOptions(_.enableAutoCancelableRunLoops)
    f

    is a function that takes the source's current set of options and returns a modified set of options that will be used to execute the source upon runAsync

  24. final def failed: Task[Throwable]

    Permalink

    Returns a failed projection of this task.

    Returns a failed projection of this task.

    The failed projection is a Task holding a value of type Throwable, emitting the error yielded by the source, in case the source fails, otherwise if the source succeeds the result will fail with a NoSuchElementException.

  25. def finalize(): Unit

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  26. final def flatMap[B](f: (A) ⇒ Task[B]): Task[B]

    Permalink

    Creates a new Task by applying a function to the successful result of the source Task, and returns a task equivalent to the result of the function.

  27. final def flatten[B](implicit ev: <:<[A, Task[B]]): Task[B]

    Permalink

    Given a source Task that emits another Task, this function flattens the result, returning a Task equivalent to the emitted Task by the source.

  28. final def foreach(f: (A) ⇒ Unit)(implicit s: Scheduler): CancelableFuture[Unit]

    Permalink

    Triggers the evaluation of the source, executing the given function for the generated element.

    Triggers the evaluation of the source, executing the given function for the generated element.

    The application of this function has strict behavior, as the task is immediately executed.

  29. final def foreachL(f: (A) ⇒ Unit): Task[Unit]

    Permalink

    Returns a new task that upon evaluation will execute the given function for the generated element, transforming the source into a Task[Unit].

    Returns a new task that upon evaluation will execute the given function for the generated element, transforming the source into a Task[Unit].

    Similar in spirit with normal foreach, but lazy, as obviously nothing gets executed at this point.

  30. final def fork: Task[Fiber[A]]

    Permalink

    Start asynchronous execution of the source suspended in the Task context.

    Start asynchronous execution of the source suspended in the Task context.

    This can be used for non-deterministic / concurrent execution. The following code is more or less equivalent with Task.parMap2 (minus the behavior on error handling and cancellation, plus forced async execution):

    def par2[A, B](ta: Task[A], tb: Task[B]): Task[(A, B)] =
      for {
        fa <- ta.fork
        fb <- tb.fork
         a <- fa
         b <- fb
      } yield (a, b)

    Note in such a case usage of parMap2 (and parMap3, etc.) is still recommended because of behavior on error and cancellation — consider that in the example above, if the first task finishes in error, the second task doesn't get cancelled.

    IMPORTANT — this operation forces an asynchronous boundary before execution, as in general this law holds:

    fa.fork <-> fa.executeAsync.start

    See start for the equivalent that does not start the task with a forced async boundary.

  31. final def forkAndForget: Task[Unit]

    Permalink

    Start asynchronous execution of the source suspended in the Task context, running it in the background and discarding the result.

    Start asynchronous execution of the source suspended in the Task context, running it in the background and discarding the result.

    Similar to fork after mapping result to Unit. Below law holds:

    task.forkAndForget <-> task.fork.map(_ => ())
  32. final def getClass(): Class[_]

    Permalink
    Definition Classes
    AnyRef → Any
  33. def hashCode(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  34. final def isInstanceOf[T0]: Boolean

    Permalink
    Definition Classes
    Any
  35. final def map[B](f: (A) ⇒ B): Task[B]

    Permalink

    Returns a new Task that applies the mapping function to the element emitted by the source.

    Returns a new Task that applies the mapping function to the element emitted by the source.

    Can be used for specifying a (lazy) transformation to the result of the source.

    This equivalence with flatMap always holds:

    scala fa.map(f) <-> fa.flatMap(x => Task.pure(f(x)))

  36. final def materialize: Task[Try[A]]

    Permalink

    Creates a new Task that will expose any triggered error from the source.

  37. final def memoize: Task[A]

    Permalink

    Memoizes (caches) the result of the source task and reuses it on subsequent invocations of runAsync.

    Memoizes (caches) the result of the source task and reuses it on subsequent invocations of runAsync.

    The resulting task will be idempotent, meaning that evaluating the resulting task multiple times will have the same effect as evaluating it once.

    Cancellation — a memoized task will mirror the behavior of the source on cancellation. This means that:

    • if the source isn't cancellable, then the resulting memoized task won't be cancellable either
    • if the source is cancellable, then the memoized task can be cancelled, which can take unprepared users by surprise

    Depending on use-case, there are two ways to ensure no surprises:

    • usage of onCancelRaiseError, before applying memoization, to ensure that on cancellation an error is triggered and then noticed by the memoization logic
    • usage of uncancelable, either before or after applying memoization, to ensure that the memoized task cannot be cancelled

    Example:

    import scala.concurrent.CancellationException
    
    val source = Task(1).delayExecution(5.seconds)
    
    // Option 1: trigger error on cancellation
    val err = new CancellationException
    val cached1 = source.onCancelRaiseError(err).memoize
    
    // Option 2: make it uninterruptible
    val cached2 = source.uncancelable.memoize

    When using onCancelRaiseError like in the example above, the behavior of memoize is to cache the error. If you want the ability to retry errors until a successful value happens, see memoizeOnSuccess.

    UNSAFE — this operation allocates a shared, mutable reference, which can break in certain cases referential transparency, even if this operation guarantees idempotency (i.e. referential transparency implies idempotency, but idempotency does not imply referential transparency).

    The allocation of a mutable reference is known to be a side effect, thus breaking referential transparency, even if calling this method does not trigger the evaluation of side effects suspended by the source.

    Use with care. Sometimes it's easier to just keep a shared, memoized reference to some connection, but keep in mind it might be better to pass such a reference around as a parameter.

    returns

    a Task that can be used to wait for the memoized value

    See also

    memoizeOnSuccess for a version that only caches successful results

  38. final def memoizeOnSuccess: Task[A]

    Permalink

    Memoizes (cache) the successful result of the source task and reuses it on subsequent invocations of runAsync.

    Memoizes (cache) the successful result of the source task and reuses it on subsequent invocations of runAsync. Thrown exceptions are not cached.

    The resulting task will be idempotent, but only if the result is successful.

    Cancellation — a memoized task will mirror the behavior of the source on cancellation. This means that:

    • if the source isn't cancellable, then the resulting memoized task won't be cancellable either
    • if the source is cancellable, then the memoized task can be cancelled, which can take unprepared users by surprise

    Depending on use-case, there are two ways to ensure no surprises:

    • usage of onCancelRaiseError, before applying memoization, to ensure that on cancellation an error is triggered and then noticed by the memoization logic
    • usage of uncancelable, either before or after applying memoization, to ensure that the memoized task cannot be cancelled

    Example:

    import scala.concurrent.CancellationException
    
    val source = Task(1).delayExecution(5.seconds)
    
    // Option 1: trigger error on cancellation
    val err = new CancellationException
    val cached1 = source.onCancelRaiseError(err).memoizeOnSuccess
    
    // Option 2: make it uninterruptible
    val cached2 = source.uncancelable.memoizeOnSuccess

    When using onCancelRaiseError like in the example above, the behavior of memoizeOnSuccess is to retry the source on subsequent invocations. Use memoize if that's not the desired behavior.

    UNSAFE — this operation allocates a shared, mutable reference, which can break in certain cases referential transparency, even if this operation guarantees idempotency (i.e. referential transparency implies idempotency, but idempotency does not imply referential transparency).

    The allocation of a mutable reference is known to be a side effect, thus breaking referential transparency, even if calling this method does not trigger the evaluation of side effects suspended by the source.

    Use with care. Sometimes it's easier to just keep a shared, memoized reference to some connection, but keep in mind it might be better to pass such a reference around as a parameter.

    returns

    a Task that can be used to wait for the memoized value

    See also

    memoize for a version that caches both successful results and failures

  39. final def ne(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  40. final def notify(): Unit

    Permalink
    Definition Classes
    AnyRef
  41. final def notifyAll(): Unit

    Permalink
    Definition Classes
    AnyRef
  42. final def onCancelRaiseError(e: Throwable): Task[A]

    Permalink

    Returns a new task that mirrors the source task for normal termination, but that triggers the given error on cancellation.

    Returns a new task that mirrors the source task for normal termination, but that triggers the given error on cancellation.

    Normally tasks that are cancelled become non-terminating. Here's an example of a cancelable task:

    val tenSecs = Task.sleep(10)
    val task = tenSecs.fork.flatMap { fa =>
      // Triggering pure cancellation, then trying to get its result
      fa.cancel.flatMap(_ => fa)
    }
    
    task.timeout(10.seconds).runAsync
    //=> throws TimeoutException

    In general you can expect cancelable tasks to become non-terminating on cancellation.

    This onCancelRaiseError operator transforms a task that would yield Task.never on cancellation into one that yields Task.raiseError.

    Example:

    import java.util.concurrent.CancellationException
    
    val tenSecs = Task.sleep(10.seconds)
      .onCancelRaiseError(new CancellationException)
    
    val task = tenSecs.fork.flatMap { fa =>
      // Triggering pure cancellation, then trying to get its result
      fa.cancel.flatMap(_ => fa)
    }
    
    task.runAsync
    // => CancellationException
  43. final def onErrorFallbackTo[B >: A](that: Task[B]): Task[B]

    Permalink

    Creates a new task that in case of error will fallback to the given backup task.

  44. final def onErrorHandle[U >: A](f: (Throwable) ⇒ U): Task[U]

    Permalink

    Creates a new task that will handle any matching throwable that this task might emit.

    Creates a new task that will handle any matching throwable that this task might emit.

    See onErrorRecover for the version that takes a partial function.

  45. final def onErrorHandleWith[B >: A](f: (Throwable) ⇒ Task[B]): Task[B]

    Permalink

    Creates a new task that will handle any matching throwable that this task might emit by executing another task.

    Creates a new task that will handle any matching throwable that this task might emit by executing another task.

    See onErrorRecoverWith for the version that takes a partial function.

  46. final def onErrorRecover[U >: A](pf: PartialFunction[Throwable, U]): Task[U]

    Permalink

    Creates a new task that on error will try to map the error to another value using the provided partial function.

    Creates a new task that on error will try to map the error to another value using the provided partial function.

    See onErrorHandle for the version that takes a total function.

  47. final def onErrorRecoverWith[B >: A](pf: PartialFunction[Throwable, Task[B]]): Task[B]

    Permalink

    Creates a new task that will try recovering from an error by matching it with another task using the given partial function.

    Creates a new task that will try recovering from an error by matching it with another task using the given partial function.

    See onErrorHandleWith for the version that takes a total function.

  48. final def onErrorRestart(maxRetries: Long): Task[A]

    Permalink

    Creates a new task that in case of error will retry executing the source again and again, until it succeeds.

    Creates a new task that in case of error will retry executing the source again and again, until it succeeds.

    In case of continuous failure the total number of executions will be maxRetries + 1.

  49. final def onErrorRestartIf(p: (Throwable) ⇒ Boolean): Task[A]

    Permalink

    Creates a new task that in case of error will retry executing the source again and again, until it succeeds, or until the given predicate returns false.

    Creates a new task that in case of error will retry executing the source again and again, until it succeeds, or until the given predicate returns false.

    In this sample we retry for as long as the exception is a TimeoutException:

    task.onErrorRestartIf {
      case _: TimeoutException => true
      case _ => false
    }
    p

    is the predicate that is executed if an error is thrown and that keeps restarting the source for as long as it returns true

  50. final def onErrorRestartLoop[S, B >: A](initial: S)(f: (Throwable, S, (S) ⇒ Task[B]) ⇒ Task[B]): Task[B]

    Permalink

    On error restarts the source with a customizable restart loop.

    On error restarts the source with a customizable restart loop.

    This operation keeps an internal state, with a start value, an internal state that gets evolved and based on which the next step gets decided, e.g. should it restart, maybe with a delay, or should it give up and re-throw the current error.

    Example that implements a simple retry policy that retries for a maximum of 10 times before giving up; also introduce a 1 second delay before each retry is executed:

    import scala.concurrent.duration._
    
    task.onErrorRestartLoop(10) { (err, maxRetries, retry) =>
      if (maxRetries > 0)
        // Next retry please; but do a 1 second delay
        retry(maxRetries - 1).delayExecution(1.second)
      else
        // No retries left, rethrow the error
        Task.raiseError(err)
    }

    A more complex exponential back-off sample:

    import scala.concurrent.duration._
    
    // Keeps the current state, indicating the restart delay and the
    // maximum number of retries left
    final case class Backoff(maxRetries: Int, delay: FiniteDuration)
    
    // Restarts for a maximum of 10 times, with an initial delay of 1 second,
    // a delay that keeps being multiplied by 2
    task.onErrorRestartLoop(Backoff(10, 1.second)) { (err, state, retry) =>
      val Backoff(maxRetries, delay) = state
      if (maxRetries > 0)
        retry(Backoff(maxRetries - 1, delay * 2)).delayExecution(delay)
      else
        // No retries left, rethrow the error
        Task.raiseError(err)
    }

    The given function injects the following parameters:

    1. error reference that was thrown 2. the current state, based on which a decision for the retry is made 3. retry: S => Task[B] function that schedules the next retry
    initial

    is the initial state used to determine the next on error retry cycle

    f

    is a function that injects the current error, state, a function that can signal a retry is to be made and returns the next task

  51. final def restartUntil(p: (A) ⇒ Boolean): Task[A]

    Permalink

    Given a predicate function, keep retrying the task until the function returns true.

  52. def runAsync(cb: Callback[A])(implicit s: Scheduler): Cancelable

    Permalink

    Triggers the asynchronous execution.

    Triggers the asynchronous execution.

    Without invoking runAsync on a Task, nothing gets evaluated, as a Task has lazy behavior.

    cb

    is a callback that will be invoked upon completion

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    returns

    a Cancelable that can be used to cancel a running task

  53. def runAsync(implicit s: Scheduler): CancelableFuture[A]

    Permalink

    Triggers the asynchronous execution.

    Triggers the asynchronous execution.

    Without invoking runAsync on a Task, nothing gets evaluated, as a Task has lazy behavior.

    UNSAFE — this operation can trigger the execution of side effects, which break referential transparency and is thus not a pure function.

    In FP code use with care, suspended in another Task or Coeval, or at the edge of the FP program.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    returns

    a CancelableFuture that can be used to extract the result or to cancel a running task.

  54. def runAsyncOpt(cb: Callback[A])(implicit s: Scheduler, opts: Options): Cancelable

    Permalink

    Triggers the asynchronous execution, much like normal runAsync, but includes the ability to specify Options that can modify the behavior of the run-loop.

    Triggers the asynchronous execution, much like normal runAsync, but includes the ability to specify Options that can modify the behavior of the run-loop.

    cb

    is a callback that will be invoked upon completion

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    opts

    a set of Options that determine the behavior of Task's run-loop.

    returns

    a Cancelable that can be used to cancel a running task

  55. def runAsyncOpt(implicit s: Scheduler, opts: Options): CancelableFuture[A]

    Permalink

    Triggers the asynchronous execution, much like normal runAsync, but includes the ability to specify Options that can modify the behavior of the run-loop.

    Triggers the asynchronous execution, much like normal runAsync, but includes the ability to specify Options that can modify the behavior of the run-loop.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    opts

    a set of Options that determine the behavior of Task's run-loop.

    returns

    a Cancelable that can be used to cancel a running task

  56. final def runOnComplete(f: (Try[A]) ⇒ Unit)(implicit s: Scheduler): Cancelable

    Permalink

    Similar to Scala's Future#onComplete, this method triggers the evaluation of a Task and invokes the given callback whenever the result is available.

    Similar to Scala's Future#onComplete, this method triggers the evaluation of a Task and invokes the given callback whenever the result is available.

    f

    is a callback that will be invoked upon completion

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    returns

    a Cancelable that can be used to cancel a running task

  57. final def runSyncMaybe(implicit s: Scheduler): Either[CancelableFuture[A], A]

    Permalink

    Tries to execute the source synchronously.

    Tries to execute the source synchronously.

    As an alternative to runAsync, this method tries to execute the source task immediately on the current thread and call-stack.

    WARNING: This method is a partial function, throwing exceptions in case errors happen immediately (synchronously).

    Usage sample:

    try task.runSyncMaybe match {
      case Right(a) => println("Success: " + a)
      case Left(future) =>
        future.onComplete {
          case Success(a) => println("Async success: " + a)
          case Failure(e) => println("Async error: " + e)
        }
    } catch {
      case NonFatal(e) =>
        println("Error: " + e)
    }

    Obviously the purpose of this method is to be used for optimizations.

    Also see runSyncUnsafe, the blocking execution mode that can only work on top of the JVM.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    returns

    Right(result) in case a result was processed, or Left(future) in case an asynchronous boundary was hit and further async execution is needed

  58. final def runSyncMaybeOpt(implicit s: Scheduler, opts: Options): Either[CancelableFuture[A], A]

    Permalink

    Tries to execute the source synchronously.

    Tries to execute the source synchronously.

    As an alternative to runAsync, this method tries to execute the source task immediately on the current thread and call-stack.

    WARNING: This method is a partial function, throwing exceptions in case errors happen immediately (synchronously).

    Usage sample:

    try task.runSyncMaybe match {
      case Right(a) => println("Success: " + a)
      case Left(future) =>
        future.onComplete {
          case Success(a) => println("Async success: " + a)
          case Failure(e) => println("Async error: " + e)
        }
    } catch {
      case NonFatal(e) =>
        println("Error: " + e)
    }

    Obviously the purpose of this method is to be used for optimizations.

    Also see runSyncUnsafe, the blocking execution mode that can only work on top of the JVM.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    opts

    a set of Options that determine the behavior of Task's run-loop.

    returns

    Right(result) in case a result was processed, or Left(future) in case an asynchronous boundary was hit and further async execution is needed

  59. final def runSyncUnsafe(timeout: Duration)(implicit s: Scheduler, permit: CanBlock): A

    Permalink

    Evaluates the source task synchronously and returns the result immediately or blocks the underlying thread until the result is ready.

    Evaluates the source task synchronously and returns the result immediately or blocks the underlying thread until the result is ready.

    WARNING: blocking operations are unsafe and incredibly error prone on top of the JVM. It's a good practice to not block any threads and use the asynchronous runAsync methods instead.

    In general prefer to use the asynchronous .runAsync and to structure your logic around asynchronous actions in a non-blocking way. But in case you're blocking only once, in main, at the "edge of the world" so to speak, then it's OK.

    Sample:

    import scala.concurrent.duration._
    
    task.runSyncUnsafe(3.seconds)

    This is equivalent with:

    import scala.concurrent.Await
    
    Await.result(task.runAsync, 3.seconds)

    Some implementation details:

    • blocking the underlying thread is done by triggering Scala's BlockingContext (scala.concurrent.blocking), just like Scala's Await.result
    • the timeout is mandatory, just like when using Scala's Await.result, in order to make the caller aware that the operation is dangerous and that setting a timeout is good practice
    • the loop starts in an execution mode that ignores BatchedExecution or AlwaysAsyncExecution, until the first asynchronous boundary. This is because we want to block the underlying thread for the result, in which case preserving fairness by forcing (batched) async boundaries doesn't do us any good, quite the contrary, the underlying thread being stuck until the result is available or until the timeout exception gets triggered.

    Not supported on top of JavaScript engines and trying to use it with Scala.js will trigger a compile time error.

    For optimizations on top of JavaScript you can use runSyncMaybe instead.

    timeout

    is a duration that specifies the maximum amount of time that this operation is allowed to block the underlying thread. If the timeout expires before the result is ready, a TimeoutException gets thrown. Note that you're allowed to pass an infinite duration (with Duration.Inf), but unless it's main that you're blocking and unless you're doing it only once, then this is definitely not recommended — provide a finite timeout in order to avoid deadlocks.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    permit

    is an implicit value that's only available for the JVM and not for JavaScript, its purpose being to stop usage of this operation on top of engines that do not support blocking threads.

  60. final def runSyncUnsafeOpt(timeout: Duration)(implicit s: Scheduler, opts: Options, permit: CanBlock): A

    Permalink

    Evaluates the source task synchronously and returns the result immediately or blocks the underlying thread until the result is ready.

    Evaluates the source task synchronously and returns the result immediately or blocks the underlying thread until the result is ready.

    WARNING: blocking operations are unsafe and incredibly error prone on top of the JVM. It's a good practice to not block any threads and use the asynchronous runAsync methods instead.

    In general prefer to use the asynchronous .runAsync and to structure your logic around asynchronous actions in a non-blocking way. But in case you're blocking only once, in main, at the "edge of the world" so to speak, then it's OK.

    Sample:

    import scala.concurrent.duration._
    
    task.runSyncUnsafe(3.seconds)

    This is equivalent with:

    import scala.concurrent.Await
    
    Await.result(task.runAsync, 3.seconds)

    Some implementation details:

    • blocking the underlying thread is done by triggering Scala's BlockingContext (scala.concurrent.blocking), just like Scala's Await.result
    • the timeout is mandatory, just like when using Scala's Await.result, in order to make the caller aware that the operation is dangerous and that setting a timeout is good practice
    • the loop starts in an execution mode that ignores BatchedExecution or AlwaysAsyncExecution, until the first asynchronous boundary. This is because we want to block the underlying thread for the result, in which case preserving fairness by forcing (batched) async boundaries doesn't do us any good, quite the contrary, the underlying thread being stuck until the result is available or until the timeout exception gets triggered.

    Not supported on top of JavaScript engines and trying to use it with Scala.js will trigger a compile time error.

    For optimizations on top of JavaScript you can use runSyncMaybe instead.

    timeout

    is a duration that specifies the maximum amount of time that this operation is allowed to block the underlying thread. If the timeout expires before the result is ready, a TimeoutException gets thrown. Note that you're allowed to pass an infinite duration (with Duration.Inf), but unless it's main that you're blocking and unless you're doing it only once, then this is definitely not recommended — provide a finite timeout in order to avoid deadlocks.

    s

    is an injected Scheduler that gets used whenever asynchronous boundaries are needed when evaluating the task

    opts

    a set of Options that determine the behavior of Task's run-loop.

    permit

    is an implicit value that's only available for the JVM and not for JavaScript, its purpose being to stop usage of this operation on top of engines that do not support blocking threads.

  61. final def start: Task[Fiber[A]]

    Permalink

    Start execution of the source suspended in the Task context.

    Start execution of the source suspended in the Task context.

    This can be used for non-deterministic / concurrent execution. The following code is more or less equivalent with Task.parMap2 (minus the behavior on error handling and cancellation):

    def par2[A, B](ta: Task[A], tb: Task[B]): Task[(A, B)] =
      for {
        fa <- ta.start
        fb <- tb.start
         a <- fa
         b <- fb
      } yield (a, b)

    Note in such a case usage of parMap2 (and parMap3, etc.) is still recommended because of behavior on error and cancellation — consider that in the example above, if the first task finishes in error, the second task doesn't get cancelled.

    IMPORTANT — this operation does start with an asynchronous boundary. You can either use fork as an alternative, or use executeAsync just before calling start, as in general this law holds:

    fa.fork <-> fa.executeAsync.start

    See fork for the equivalent that does starts the task with a forced async boundary.

  62. final def synchronized[T0](arg0: ⇒ T0): T0

    Permalink
    Definition Classes
    AnyRef
  63. final def timeout(after: FiniteDuration): Task[A]

    Permalink

    Returns a Task that mirrors the source Task but that triggers a TimeoutException in case the given duration passes without the task emitting any item.

  64. final def timeoutTo[B >: A](after: FiniteDuration, backup: Task[B]): Task[B]

    Permalink

    Returns a Task that mirrors the source Task but switches to the given backup Task in case the given duration passes without the source emitting any item.

  65. final def to[F[_]](implicit F: Async[F], s: Scheduler): F[A]

    Permalink

    Converts the source Task to any data type that implements either cats.effect.Concurrent or cats.effect.Async.

    Converts the source Task to any data type that implements either cats.effect.Concurrent or cats.effect.Async.

    This operation discriminates between Concurrent and Async data types by using their subtyping relationship (Concurrent <: Async), therefore:

    • in case the F data type implements cats.effect.Concurrent, then the resulting value is interruptible if the source task is (e.g. a conversion to cats.effect.IO will preserve Monix's Task cancelability)
    • otherwise in case the F data type implements just cats.effect.Async, then the conversion is still allowed, however the source's cancellation logic gets lost

    Example:

    import cats.effect.IO
    
    Task.eval(println("Hello!"))
      .delayExecution(5.seconds)
      .to[IO]

    Note a Scheduler is required because converting Task to something else means executing it.

    F

    is the cats.effect.Async instance required in order to perform the conversions; and if this instance is actually a cats.effect.Concurrent, then the resulting value is also cancelable

    s

    is the Scheduler needed in order to evaluate the source, being required in Task's runAsync

  66. final def toIO(implicit s: Scheduler): IO[A]

    Permalink

    Converts the source to a cats.effect.IO value.

    Converts the source to a cats.effect.IO value.

    val task: Task[Unit] = Task
      .eval(println("Hello!"))
      .delayExecution(5.seconds)
    
    // Conversion; note the resulting IO is also
    // cancelable if the source is
    val io: IO[Unit] = task.toIO

    This is an alias for to, but specialized for IO. You can use either with the same result.

    s

    is the Scheduler needed in order to evaluate the source, being required in Task's runAsync

  67. final def toReactivePublisher(implicit s: Scheduler): Publisher[A]

    Permalink

    Converts a Task to an org.reactivestreams.Publisher that emits a single item on success, or just the error on failure.

    Converts a Task to an org.reactivestreams.Publisher that emits a single item on success, or just the error on failure.

    See reactive-streams.org for the Reactive Streams specification.

  68. def toString(): String

    Permalink

    Returns a string representation of this task meant for debugging purposes only.

    Returns a string representation of this task meant for debugging purposes only.

    Definition Classes
    Task → AnyRef → Any
  69. final def transform[R](fa: (A) ⇒ R, fe: (Throwable) ⇒ R): Task[R]

    Permalink

    Creates a new Task by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    Creates a new Task by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    This function is similar with map, except that it can also transform errors and not just successful results.

    fa

    function that transforms a successful result of the receiver

    fe

    function that transforms an error of the receiver

  70. final def transformWith[R](fa: (A) ⇒ Task[R], fe: (Throwable) ⇒ Task[R]): Task[R]

    Permalink

    Creates a new Task by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    Creates a new Task by applying the 'fa' function to the successful result of this future, or the 'fe' function to the potential errors that might happen.

    This function is similar with flatMap, except that it can also transform errors and not just successful results.

    fa

    function that transforms a successful result of the receiver

    fe

    function that transforms an error of the receiver

  71. final def uncancelable: Task[A]

    Permalink

    Makes the source Task uninterruptible such that a cancel signal (e.g.

    Makes the source Task uninterruptible such that a cancel signal (e.g. Fiber.cancel) has no effect.

    val cancelable = Task
      .eval(println("Hello!"))
      .delayExecution(10.seconds)
      .runAsync
    
    // No longer works
    cancelable.cancel()
    
    // After 10 seconds
    //=> Hello!
  72. final def wait(): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  73. final def wait(arg0: Long, arg1: Int): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  74. final def wait(arg0: Long): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  75. final def zip[B](that: Task[B]): Task[(A, B)]

    Permalink

    Zips the values of this and that task, and creates a new task that will emit the tuple of their results.

  76. final def zipMap[B, C](that: Task[B])(f: (A, B) ⇒ C): Task[C]

    Permalink

    Zips the values of this and that and applies the given mapping function on their results.

Inherited from Serializable

Inherited from Serializable

Inherited from AnyRef

Inherited from Any

Ungrouped