What's the Scala way to implement a retry-able call like this one?

前端 未结 14 1748
甜味超标
甜味超标 2020-11-29 16:08

Still the newbie in Scala and I\'m now looking for a way to implement the following code on it:

@Override
public void store(InputStream source, String destin         


        
14条回答
  •  北荒
    北荒 (楼主)
    2020-11-29 16:48

    I ended up adapting a previous answer to allow filtering on which exceptions to retry on:

      /**
       * Attempt 'fn' up to 'attempts' times, retrying only if 'forExceptions' returns true for retry-able exceptions.
       */
      def retry[T](attempts: Int, forExceptions: (Throwable) => Boolean)(fn: => T): T =
      {
        // toStream creates a lazily evaluated list, which we map to a try/catch block resulting in an Either
        val tries = (1 to attempts).toStream map
          {
            n =>
              try
                Left(fn)
              catch
                {
                  case e if forExceptions(e) => Right(e)
                }
          }
    
        // find the first 'Either' where left is defined and return that, or if not found, return last
        // exception thrown (stored as 'right').  The cool thing is that because of lazy evaluation, 'fn' is only
        // evaluated until it success (e.g., until Left is found)
        tries find (_ isLeft) match
        {
          case Some(Left(result)) => result
          case _ => throw tries.reverse.head.right.get
        }
    
      }
    

    You can call in two ways:

    val result = retry(4, _.isInstanceOf[SomeBadException])
    {
       boom.doit()
    }
    

    or with partial functions (also showing version where don't care about return value)

        def pf: PartialFunction[Throwable, Boolean] =
        {
          case x: SomeOtherException => true
          case _ => false
        }
    
       retry(4, pf)
       {
          boom.doit()
       }
    

提交回复
热议问题