Search code examples
scalazio

How to repeat a message to console using a schedule


I am trying to learn how schedules work, and I just want to display a simple message to the console using a schedule.

import zio.console._
import zio._
import scala.util.Try
import zio.duration._
import zio.clock._

object MyApp extends zio.App {

  def run(args: List[String]) =
    myAppLogic.exitCode

  val myAppLogic =
    for {
      sequential = Schedule.recurs(10) andThen Schedule.spaced(1.second)
      _ <-  ZIO.effectTotal{ "hello" }.retry(sequential)
    } yield ()

}

I am getting this error:

This error handling operation assumes your effect can fail. However, your effect has Nothing for the error type, which means it cannot fail, so there is no need to handle the failure. To find out which method you can use instead of this operation, please see the reference chart at: https://zio.dev/docs/can_fail [error] _ <- ZIO.effectTotal{ "hello" }.retry(sequential)

I am returning a Task[String] which has a throwable error type. If I replace effectTotal with effect then I don't get a compile error, but the program just exists without repeating the word hello even once.

What concept am I missing here?


Solution

  • First of all you can't have = in the first line of a for-comprehension. You need to wrap your pure value in ZIO.succeed or leave it outside the for-comprehension.

    "Hello" is a pure string. You could use ZIO.effectTotal but technically it doesn't produce any side effect so you should also use succeed here.

    retry retries on failure, but effectTotal / succeed cannot fail. You should be using repeat instead.

    import zio._
    import zio.duration._
    
    object MyApp extends zio.App {
      def run(args: List[String]) =
        myAppLogic.exitCode
    
      val myAppLogic =
        for {
          sequential <- ZIO.succeed(Schedule.recurs(10) andThen Schedule.spaced(1.second))
          _ <-  ZIO.succeed("hello").repeat(sequential)
        } yield ()
    }
    

    Now with errors fixed it still doesn't display your texts because you are just producing values (not a side effect) without printing them (side effect).

    The correct code should be something like:

    import zio._
    import zio.duration._
    import zio.console._
    
    object MyApp extends zio.App {
      def run(args: List[String]) =
        myAppLogic.exitCode
    
      //leave this out of the for-comprehension
      val sequential = Schedule.recurs(10) andThen Schedule.spaced(1.second)
    
      val myAppLogic = putStrLn("hello").repeat(sequential)
    
    //  Or you could suspend the `println` side effect with `effectTotal` (doesn't fail but produces side effects)
    //  val myAppLogicAlt = ZIO.effectTotal(println("hello")).repeat(sequential)
    }