如何在ZIO中实现多条件独立计数的重试Schedule
ZIO实现多条件独立计数的重试逻辑
要实现两个独立条件的重试(各自有最大重试次数),不能直接用||组合两个Schedule(因为会共享状态,无法分别统计次数),需要自定义带独立状态的Schedule,分别跟踪每个条件的重试次数。
完整实现代码
package com.mycompany import zio.{ExitCode, Schedule, Task, URIO, ZIO, ZIOAppDefault} import scala.util.Random object Main3 extends ZIOAppDefault { // 模拟服务请求,返回0-10之间的随机浮点数 def makeRequest: Task[Float] = ZIO.attempt { new Random().nextFloat() * 10 } // 自定义Schedule:分别跟踪两个条件的重试次数 def makeSchedule(): Schedule[(Int, Int), Float, Float] = { Schedule.stateful[(Int, Int), Float, Float] { case ((errorRetryCount, insufficientRetryCount), response) => // 条件1:响应为错误数据(<=3),最多重试3次 if (response <= 3) { if (errorRetryCount < 3) { val newState = (errorRetryCount + 1, insufficientRetryCount) ZIO.log(s"错误数据重试,当前次数: ${errorRetryCount + 1}") *> ZIO.succeed((newState, Some(response))) } else { ZIO.log("错误数据重试次数已达上限(3次),停止重试") *> ZIO.succeed(((errorRetryCount, insufficientRetryCount), None)) } } // 条件2:响应数据不足(>=9),最多重试5次 else if (response >= 9) { if (insufficientRetryCount < 5) { val newState = (errorRetryCount, insufficientRetryCount + 1) ZIO.log(s"数据不足重试,当前次数: ${insufficientRetryCount + 1}") *> ZIO.succeed((newState, Some(response))) } else { ZIO.log("数据不足重试次数已达上限(5次),停止重试") *> ZIO.succeed(((errorRetryCount, insufficientRetryCount), None)) } } // 响应符合要求,停止重试 else { ZIO.log("响应符合预期,停止重试") *> ZIO.succeed(((errorRetryCount, insufficientRetryCount), None)) } } } override def run: URIO[Any, ExitCode] = { makeRequest .repeat(makeSchedule()) .tap(res => ZIO.log(f"最终结果: $res%.2f")) .exitCode } }
关键说明
- 状态设计:用
(Int, Int)作为Schedule的状态,分别记录「错误数据」和「数据不足」的重试次数,初始状态为(0, 0)。 - 条件判断:每次请求返回后,先判断响应属于哪种情况,再检查对应重试次数是否达到上限:
- 若未达上限,更新对应计数并继续重试;
- 若已达上限或响应符合要求,停止重试并返回结果。
- 日志跟踪:通过日志可以清晰看到每个条件的重试次数和停止原因,方便调试。
运行效果示例
假设某次请求序列:
- 返回
2.1→ 触发错误数据重试,次数1 - 返回
9.5→ 触发数据不足重试,次数1 - 返回
9.7→ 触发数据不足重试,次数2 - 返回
4.3→ 响应符合预期,停止重试
最终输出结果为4.30,日志会完整记录每一步的重试逻辑。
内容的提问来源于stack exchange,提问作者Art
相关产品推荐
相关产品推荐

