I am trying to achieve something like the following code
def getUsers: EitherT[Future, String, Response] = {
for {
users <- EitherT(userRepository.findAll) // this method would retrieve a Future[Either[String, Seq[User]]]
user <- users
friends <- EitherT(userRepository.findFriends(user.id))
} yield new Response(user, friends)
}
I understand that this is not possible, because EitherT
does not manage foreach
.
case class User(id: Long, name: String, email: String)
case class Response(user: User, friends: Seq[User])
Which would be a good way to solve this?
Since you are finding all users, you will have multiple users with their respective friends, so I modified your return value to return a List
of Response
s instead. Then perhaps you want to do something like this:
import cats.data.EitherT
import cats.syntax.traverse._
import cats.instances.list._
import cats.instances.future._
import scala.concurrent.Future
def getUsers: EitherT[Future, String, List[Response]] = {
EitherT(userRepository.findAll).flatMap { users =>
users.toList.traverse(user => EitherT(userRepository.findFriends(user.id)).map(Response(user, _)))
}
}
Make sure you have an implicit ExecutionContext
in scope or import scala.concurrent.ExecutionContext.Implicits.global
.