ZIO 2 Example: Print values after a random delay (and the ZIO error channel)

As a brief note today, here’s a little ZIO 2 example that shows how to print a series of values with a random delay in between each value that’s printed.

Note that there are different ways to implement randomWaitTimeInSeconds ... for instance, it could return a Duration, but I just have it return an Int.

I also use ZIO.foreach to generate the values in a range, and that could be handled differently.

Another thing I do is use an exception inside ZIO.fail, and I do that because I want that error to be a Throwable on the ZIO “error channel” (i.e., the E parameter in ZIO[R, E, A].)

That being said, here’s this ZIO 2 example code:

package zio_random_delay

import zio.*
import zio.Console.*
import com.alvinalexander.zio.ZioTypes.*

object ZioRandomIntervalPrinter extends ZIOAppDefault:

    final class InvalidRangeException(val message: String) extends Throwable(message)

    // Task[Int] == ZIO[Any, Throwable, Int]
    def randomWaitTimeInSeconds(minInclusive: Int, maxExclusive: Int): Task[Int] =
        if minInclusive >= maxExclusive then
            ZIO.fail(InvalidRangeException("minInclusive must be less than maxExclusive"))
            Random.nextIntBetween(minInclusive, maxExclusive)

    val printNumbersAtRandomIntervals: ZIO[Any, Throwable, Unit] =
        ZIO.foreach(1 to 3) { num =>
                waitTime <- randomWaitTimeInSeconds(1, 4)
                _        <- printLine(s"num = $num, wait = $waitTime seconds")
                _        <- Clock.sleep(waitTime.seconds)

    // TODO: other ways to handle this
    val run: Task[Unit] =
            failure => printLineError(s"FAILURE = $failure"),
            success => printLine(     s"SUCCESS = $success")

Although the results are random, the output from this example ZIO 2 application looks like this:

num = 1, wait = 3 (seconds)
num = 2, wait = 3 (seconds)
num = 3, wait = 1 (seconds)