All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tyrian.Task.scala Maven / Gradle / Ivy

There is a newer version: 0.11.0
Show newest version
package tyrian

import scala.annotation.nowarn

/** A task describes some side-effect to perform.
  *
  * Examples:
  *
  *   - An XHR
  *
  * @tparam Err
  *   Type of error produced the task
  * @tparam Success
  *   Type of successful value produced by the task
  */
sealed trait Task[+Err, +Success]:

  /** Transforms successful values */
  def map[Success2](f: Success => Success2): Task[Err, Success2] =
    Task.Mapped(this, f)

  /** Combines to tasks in parallel */
  def product[Success2, Err2 >: Err](that: Task[Err2, Success2]): Task[Err2, (Success, Success2)] =
    Task.Multiplied(this, that)

  /** Sequentially applies this task and then another task given by the function `f` */
  def flatMap[Success2, Err2 >: Err](f: Success => Task[Err2, Success2]): Task[Err2, Success2] =
    Task.FlatMapped(this, f)

  /** Turns this task into a command by transforming errors and successful values according to the `f` function
    */
  def attempt[Msg](toMessage: Either[Err, Success] => Msg): Cmd[Msg] =
    Cmd.RunTask(this, toMessage)

  /** Turns this task (that never fails) into a command
    */
  @nowarn // Can never fail, but is doing an unsafe projection.
  def perform[Err2 >: Err](using Err2 =:= Nothing): Cmd[Success] =
    Cmd.RunTask[Err, Success, Success](this, _.toOption.get)

object Task:

  /** Something that produces successful values of type `Value` and error values of type `Err`
    */
  trait Observable[Err, Value] {

    /** Run this observable and attaches the given `observer` to its notifications.
      * @return
      *   a cancelable for this observable
      */
    def run(observer: Observer[Err, Value]): Cancelable
  }

  /** An observer of successful values of type `Value` and errors of type `Err`
    */
  trait Observer[Err, Value] {
    def onNext(value: Value): Unit
    def onError(error: Err): Unit
  }

  trait Cancelable {
    def cancel(): Unit
  }

  /** A task that is a fire and forget side effect */
  final case class SideEffect(thunk: () => Unit) extends Task[Nothing, Unit]

  /** A task that succeeded with the given `value` */
  final case class Succeeded[A](value: A) extends Task[Nothing, A]

  /** A task that failed with the given `error` */
  final case class Failed[A](error: A) extends Task[A, Nothing]

  /** A task that runs the given `observable` */
  final case class RunObservable[Err, Success](observable: Observable[Err, Success]) extends Task[Err, Success]

  final case class Recovered[Err, Success](task: Task[Err, Success], recoverWith: Err => Task[Err, Success])
      extends Task[Err, Success]

  final case class Mapped[Err, Success, Success2](task: Task[Err, Success], f: Success => Success2)
      extends Task[Err, Success2]

  final case class Multiplied[Err, Success, Success2](task1: Task[Err, Success], task2: Task[Err, Success2])
      extends Task[Err, (Success, Success2)]

  final case class FlatMapped[Err, Success, Success2](task: Task[Err, Success], f: Success => Task[Err, Success2])
      extends Task[Err, Success2]




© 2015 - 2025 Weber Informatics LLC | Privacy Policy