Home > Net >  Collect all of the successes and failures of a sequence of ZIOs together?
Collect all of the successes and failures of a sequence of ZIOs together?

Time:12-29

I have a bunch of IOs, 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)
      )
    }
  }
}
  • Related