Currently my error handling is not working as I want to, this is what I am trying to do:
- UserApi.insert fails, return its error and don't continue
- WorkApi.insert fails, return its error after calling UserApi.delete
- WorkApi.assign fails, return its error after calling WorkApi.delete and UserApi.delete
So in summary, UserApi.insert is called, if it is successfull, continue to #2. If WorkApi.insert is successfull, continue. And so on, if the current step fails, you have to reverse the previous one.
Also it is important to return the most relevant error for the Api call that failed.
If all calls were successful, I want to return the first calls value which is a User.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}
val u1 = User("u1")
val w1 = Work("w1")
val resp = for {
insertResp <- UserApi.insert(u1)
workInsertResp <- WorkApi.insert(w1)
workAssignResp <- WorkApi.assign(w1)
} yield insertResp
println("ending...")
resp onComplete {
case Success(r) => println(r)
case Failure(t) => println(t)
}
case class User(name: String)
case class Work(name: String)
case class MyError(name: String)
object UserApi {
def insert(user: User): Future[Either[MyError, User]] =
if (user.name == "u1") Future(Right(user))
else Future(Left(MyError("UserApi.insert")))
def delete(user: User): Future[Either[MyError, String]] =
Future(Right("UserApi.delete"))
}
object WorkApi {
def insert(work: Work): Future[Either[MyError, Work]] =
if (work.name == "w1") Future(Right(work))
else Future(Left(MyError("WorkApi.insert")))
def delete(work: Work): Future[Either[MyError, Work]] = Future(Right(work))
def assign(work: Work): Future[Either[MyError, Work]] =
if (work.name == "w1") Future(Right(work))
else Future(Left(MyError("WorkApi.assign")))
}
Currently I am not sure how to bubble the correct error up.
Note: I am using scala 2.13.x, and I am not using other frameworks just plain Scala.