Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package futureeitherapplicativestack
import cats._
import cats.data._
import cats.implicits._
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.concurrent.ExecutionContext.Implicits.global
object Types {
type Result[A] = Validated[Vector[String], A]
type FutureResult[A] = Future[Result[A]]
implicit val futureEither = {
Applicative[Future].compose[Result]
}
}
import Types._
object IndependentTasks {
def task1(): FutureResult[String] = Future {
Thread.sleep(5000)
println("[LOG] task 1 executed.")
"result of task 1".valid
}
def task2(): FutureResult[String] = Future {
Thread.sleep(5000)
Vector("An error occurred while executing task 2").invalid
}
def task3(): FutureResult[String] = Future {
Thread.sleep(5000)
Vector("An error occurred while executing task 3").invalid
}
def task4(): FutureResult[String] = Future {
Thread.sleep(5000)
println("[LOG] task 4 executed.")
"result of task 4".valid
}
}
import IndependentTasks._
object Main extends App {
// execute independent tasks in parallel
val result = (
task1() |@|
task2() |@|
task3() |@|
task4()).tupled
val evalResult = Await.result(result, Duration.Inf).fold(
errs => s"[FAILURE] $errs",
_ => "[SUCCESS] All tasks executed successfully."
)
println(evalResult)
}
package futureeithermonadstack
import cats._
import cats.data._
import cats.implicits._
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import scala.concurrent.ExecutionContext.Implicits.global
object Types {
type FutureEither[A] = EitherT[Future, String, A]
}
import futureeithermonadstack.Types.FutureEither
object DependentTasks {
def task1(input: String): FutureEither[String] = EitherT.right[Future, String, String](Future {
Thread.sleep(2000)
println("[LOG] task 1 executed.")
"result of task 1"
})
def task2(input: String): FutureEither[String] = EitherT.right[Future, String, String](Future {
Thread.sleep(2000)
println("[LOG] task 2 executed.")
"result of task 2"
})
def task3(input: String): FutureEither[String] = EitherT.left[Future, String, String](Future {
Thread.sleep(2000)
"An error occurred while running task 3."
})
def task4(input: String): FutureEither[String] = EitherT.right[Future, String, String](Future {
Thread.sleep(2000)
println("[LOG] task 4 executed.")
"result of task 4"
})
}
import scala.concurrent.Await
import DependentTasks._
object Main extends App {
// execute dependent tasks with fail fast semantics
val result = for {
t1 <- task1("foo")
t2 <- task2(t1)
t3 <- task3(t2)
t4 <- task4(t3)
} yield ()
val evalResult = Await.result(result.value, Duration.Inf).fold(
err => s"[FAILURE] $err",
res => "[SUCCESS] All tasks executed successfully."
)
println(evalResult)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment