【问题标题】:Scala : Retry with try/catch for exception handlingScala:使用 try/catch 重试异常处理
【发布时间】:2023-03-08 23:19:02
【问题描述】:

我正在尝试为 JSON 转换添加重试逻辑。将对象转换为 json 时,如果有任何异常,我会重试 3 次。我在做:

   var mapper = new ObjectMapper() with ScalaObjectMapper
  intializeMapper( )

  def intializeMapper() = {
    // jackson library does not support seralization and deserialization of
    // of scala classes like List and Map, this is needed to support it
    mapper.registerModule( DefaultScalaModule )
    // enables parsing of NaN. Enabling it here as JsonUtil class currently in
    // use supports it.
    mapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true )
    mapper.setSerializationInclusion(Include.NON_NULL)
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

  } 


 def getPersonRDD(result: DataFrame): RDD[(String, String)] = {

    val finalValue = result.rdd.map({
      r =>
        val customerId = r.getAs[String](CUSTOMER_ID)
        val itemId = r.getAs[Map[String, Int]](ITEM_ID)
        val itemName = r.getAs[Map[String, Int]](ITEM_NAME)


        val person = Person(itemId, itemName)

        val jsonString = toJson(person)

        (customerId, jsonString)

    })

    return finalValue
  }

  def fromJson(json: String, clazz: Class[_]) = {
    mapper.readValue(json, clazz)
  }

  def toJson(value: Any): String = {

    var jsonString: String = " "
    jsonString = mapper.writeValueAsString(value)

    try {
      fromJson(jsonString, clazz)
      return jsonString
    } catch {
      case Exception => {

        publishMetrics(PARSING_EXCEPTION, 1.0)
        val result = util.Try(retry() {
          jsonString = mapper.writeValueAsString(value)
          val features = fromJson(jsonString, clazz)
        })

        result match {
          case util.Success(value) => jsonString

          case util.Failure(error) => {
            log.error("Error while parsing JSON " + jsonString)
            return jsonString
          }

        }

      }
    }

  }

  // Returning T, throwing the exception on failure
  @annotation.tailrec
  def retry[T](n: Int = 3)(fn: => T): T = {
    util.Try {
      fn
    } match {
      case util.Success(x) => x
      case _ if n > 1 => retry(n - 1)(fn)
      case util.Failure(e) => throw e
    }
  }

case class Person(itemId: Map[String, Int], itemName: Map[String, Int]) extends Serializable

这是正确的吗?我是 Scala 的新手。有人可以建议我是否有更好的方法来实现这一目标? Scala 中是否有预定义的重试逻辑?我尝试为 JSON 转换添加重试逻辑的原因是由于我使用的 Jackson 版本(我现在无法更改),有时我的 writeValueAsString 会导致 JSON 不完整。

【问题讨论】:

  • 你正在解析 Json,它是确定性的。为什么你会期望另一个时间得到不同的结果?
  • 您能否简要介绍一下“映射器”是什么以及它在做什么?它是否有能力以某种方式纠正无效的 json 输入?如果没有,重试有什么意义?
  • @NathanHughes 因为 JacksonJackson-databind = 2.6.x;杰克逊核心 = 2.6.x; Jackson-annotations = 2.6.x;杰克逊模块scala = 2.6.5;我的转换结果是部分 json,这是非常不确定的。
  • @AndreyTyukin 输入只是我正在转换为 JSON 的案例类
  • 多么奇怪。可能是您正在读取的这个数据框是惰性填充的还是什么?

标签: json scala apache-spark try-catch user-defined-functions


【解决方案1】:

您的重试功能似乎正确。我能想到的唯一缺陷是,如果您预计某些事情会失败,最好将返回类型设为Try[T],这样您就可以在外部以 scala 方式处理它。

这是我的实现之一:

def retry[T](n: Int)(block: => T): Try[T] = {
  val stream = Stream.fill(n)(Try(block))
  stream find (_.isSuccess) getOrElse stream.head
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-24
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多