I have a bunch of IO
s, all of which may have either succeeded or failed:
val result: Seq[IO[MyFailure, MySuccess]] = ...
I need to summarize the results such that I can examine all the failures and all the successes together:
case class MySummary(failures: Seq[MyFailure], successes: Seq[MySuccess])
def makeSummary(results: Seq[IO[MyFailure, MySuccess]]): UIO[MySummary] = ???
At first this seemed quite similar to foreach
, but upon closer inspection I see that that doesn't help here. For Future
I'd normally use sequence
, and for Seq[Either[A,B]]
I could use partitionMap
. What is the equivalent method in ZIO named?
CodePudding user response:
You can't examine all failures with Future.sequence
, you will only get back the first failure if there is any.
The ZIO equivalent for Future.sequence
would be ZIO.collectAll
which is pretty much equivalent to ZIO.foreach(result)(identity)
.
If you really need to accumulate all errors then you should probably use ZIO.validate
and for partitioning there's also ZIO.partition
.
Some code for comparison:
val result: Seq[IO[MyFailure, MySuccess]] = ???
val withCollectAll: IO[MyFailure, Seq[MySuccess]] = ZIO.collectAll(result)
val withForeach: IO[MyFailure, Seq[MySuccess]] = ZIO.foreach(result)(identity)
val withValidate: IO[::[MyFailure], Seq[MySuccess]] = ZIO.validate(result)(identity) //`::` just means that the list cannot be empty
val withPartition: UIO[(Iterable[MyFailure], Iterable[MySuccess])] = ZIO.partition(result)(identity)
Code for makeSummary
with ZIO.partition
:
def makeSummary(results: Seq[IO[MyFailure, MySuccess]]): UIO[MySummary] =
ZIO.partition(result)(identity).map { case (f, s) => MySummary(f.toSeq, s.toSeq) }
CodePudding user response:
I'm not familiar with ZIO, there might be a built-in way to achieve the same.
I would go with something like the following:
def makeSummary(results: Seq[IO[MyFailure, MySuccess]]): UIO[MySummary] = {
results.foldLeft(ZIO.succeed(MySummary(Seq(), Seq()))) { (acc, io) =>
acc.flatMap { summary =>
io.fold(
err => summary.copy(failures = summary.failures : err),
suc => summary.copy(successes = summary.succcesses : suc)
)
}
}
}