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

前端 未结 14 1700
甜味超标
甜味超标 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 17:05

    If you want control of which exceptions you retry, you can use methods in scala.util.control.Exception:

    import java.io._
    import scala.util.control.Exception._
    
    def ioretry[T](n: Int)(t: => T) = (
      Iterator.fill(n){ failing[T](classOf[IOException]){ Option(t) } } ++
      Iterator(Some(t))
    ).dropWhile(_.isEmpty).next.get
    

    (As written, it will also retry on null; that's the Option(t) part. If you want nulls to be returned, use Some(t) inside the iterator fill instead.)

    Let's try this out with

    class IoEx(var n: Int) {
      def get = if (n>0) { n -= 1; throw new IOException } else 5
    }
    val ix = new IoEx(3)
    

    Does it work?

    scala> ioretry(4) { ix.get }
    res0: Int = 5
    
    scala> ix.n = 3
    
    scala> ioretry(2) { ix.get }
    java.io.IOException
        at IoEx.get(<console>:20)
        ...
    
    scala> ioretry(4) { throw new Exception }
    java.lang.Exception
        at $anonfun$1.apply(<console>:21)
        ...
    

    Looks good!

    0 讨论(0)
  • 2020-11-29 17:09

    There is an existing library that can help with that, called retry, and there is a Java library too, called guava-retrying.

    Here are some examples of using retry:

    // retry 4 times
    val future = retry.Directly(4) { () => doSomething }
    
    // retry 3 times pausing 30 seconds in between attempts
    val future = retry.Pause(3, 30.seconds) { () => doSomething }
    
    // retry 4 times with a delay of 1 second which will be multipled
    // by 2 on every attempt
    val future = retry.Backoff(4, 1.second) { () => doSomething }
    
    0 讨论(0)
提交回复
热议问题