I am using ZIO and my task is to retry request to some service with such logic (simplified):
I am planning to use .repeat function from ZIO, but can not figure out how to write schedule which will count retries individually for each condition.
package com.mycompany
import zio.Schedule.WithState
import zio.{ExitCode, Schedule, Task, URIO, ZIO, ZIOAppDefault}
import scala.util.Random
object Main3 extends ZIOAppDefault {
def makeRequest: Task[Float] = ZIO.attempt {
new Random().nextFloat() * 10
}
def makeSchedule(): WithState[(Unit, Unit), Any, Float, Float] = {
val firstCondition =
Schedule.recurUntil[Float](float => float > 3)
// TODO: make only 3 tries for this condition
.onDecision {
case (input, value, decision) => ZIO.log(s"FirstCondition: ${input}, ${value}, ${decision}")
}
val secondCondition =
Schedule.recurUntil[Float](float => float < 9)
// TODO: make only 5 tries for this condition
.onDecision {
case (input, value, decision) => ZIO.log(s"SecondCondition: ${input}, ${value}, ${decision}")
}
firstCondition.||(secondCondition).map(_._1)
}
override def run: URIO[Any, ExitCode] = {
makeRequest
.repeat(makeSchedule())
.tap(res => ZIO.log(f"RESULT IS: $res"))
.exitCode
}
}
I found the solution:
.repetitions
.whileOutput(repetition => repetition < 3)
.passthrough[Float]
is doing the job. Calling passthrough[Float] allows to align types and get result from repeat. Final code snippet is
package com.mycompany
import zio.Schedule.WithState
import zio.{ExitCode, Schedule, Task, URIO, ZIO, ZIOAppDefault}
import scala.util.Random
object Main3 extends ZIOAppDefault {
def makeRequest: Task[Float] = ZIO.attempt {
new Random().nextFloat() * 10
}
def makeSchedule() = {
val firstCondition =
Schedule.recurUntil[Float](float => float > 8)
.repetitions
.whileOutput(repetition => repetition < 3)
.passthrough[Float]
.onDecision {
case (input, value, decision) => ZIO.log(s"FirstCondition: ${input}, ${value}, ${decision}")
}
val secondCondition: WithState[(Unit, Long), Any, Float, Float] =
Schedule.recurUntil[Float](float => float < 9)
.repetitions
.whileOutput(repetition => repetition < 5)
.passthrough[Float]
.onDecision {
case (input, value, decision) => ZIO.log(s"SecondCondition: ${input}, ${value}, ${decision}")
}
firstCondition.||(secondCondition).map(_._1)
}
override def run: URIO[Any, ExitCode] = {
makeRequest
.repeat(makeSchedule())
.tap(res => ZIO.log(f"RESULT IS: $res"))
.exitCode
}
}