Scala中使用Resilience4J重试逻辑遇类型不匹配错误的解决方法
解决Resilience4J重试逻辑的类型不匹配问题
核心问题分析
你的错误源于两个关键点:
- 类型适配问题:Resilience4J的
Decorators.ofSupplier期望的是Java的Supplier接口,虽然Scala的Function0可以隐式转换,但返回值的泛型需要明确统一。 - 重试触发逻辑不匹配:默认重试仅在抛出异常时触发,而你代码中部分错误场景是返回
Some[(String,String)](正常返回值),不会触发重试,同时导致类型推断异常。
解决方案一:将业务错误转为异常触发重试(推荐)
通过抛出自定义异常,让Resilience4J的默认重试逻辑捕获并触发重试,同时统一返回值类型:
- 先定义自定义异常类:
case class VertexTaxException(code: String, message: String) extends Exception(s"Tax Error [$code]: $message")
- 修改原有代码,将返回
Some的场景改为抛出异常:
val reversalRequestResult = Decorators.ofSupplier(() => { determinationService.getTax(getTaxRequest, runID) match { case Success(getTaxResponse) => if (vertexComplianceExceptionHandler.containsGrpcResponseExceptions(getTaxResponse)) { val (errorCode, errorMsg) = vertexComplianceExceptionHandler.handleGrpcResponseExceptions(getTaxResponse) LOGGER.error("Response has a failure/unsuccessful status for a invoice request") throw VertexTaxException(errorCode, errorMsg) } else { eventInfoCase.record_status = VertexComplianceConstant.RECORD_STATUS_SUCCESS getTaxResponse // 成功时返回具体响应对象 } case Failure(exception) => val (errorCode, errorMsg) = vertexComplianceExceptionHandler.handleHardGrpcExceptions(exception) throw VertexTaxException(errorCode, errorMsg) } }).withRetry(vertexGetTaxResilience.getDefaultRetryInstance()) .get()
- 确保重试配置(
getDefaultRetryInstance())包含对VertexTaxException的重试规则,若默认配置是重试所有异常则无需额外修改。
解决方案二:自定义重试规则,支持返回值判断
若希望保留Option返回值结构,可通过自定义RetryConfig指定当返回Some时触发重试:
import io.github.resilience4j.retry.Retry import io.github.resilience4j.retry.RetryConfig import java.time.Duration // 构建自定义重试配置 val retryConfig = RetryConfig.custom() .maxAttempts(3) // 最大重试次数 .waitDuration(Duration.ofSeconds(1)) // 重试间隔 .retryOnResult[Option[(String, String)]] { result => result.isDefined // 返回Some时触发重试 } .retryOnException(_ => true) // 异常场景也触发重试 .build() val retry = Retry.of("vertex-get-tax-retry", retryConfig) // 用Retry.decorateSupplier包装逻辑 val reversalRequestResult = Retry.decorateSupplier(retry, () => { determinationService.getTax(getTaxRequest, runID) match { case Success(getTaxResponse) => if (vertexComplianceExceptionHandler.containsGrpcResponseExceptions(getTaxResponse)) { LOGGER.error("Response has a failure/unsuccessful status for a invoice request") Some(vertexComplianceExceptionHandler.handleGrpcResponseExceptions(getTaxResponse)) } else { eventInfoCase.record_status = VertexComplianceConstant.RECORD_STATUS_SUCCESS None } case Failure(exception) => Some(vertexComplianceExceptionHandler.handleHardGrpcExceptions(exception)) } }).get()
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

