import scala.util.control.Exception.allCatch object RetryUtil { case class RetryException(throwables: List[Throwable]) extends Exception def retry[T](retryLimit: Int, retryInterval: Int, shouldCatch: Throwable => Boolean)(f: => T): T = retry(Stream.fill(retryLimit)(retryInterval), shouldCatch)(f) def retry[T](intervals: Stream[Int], shouldCatch: Throwable => Boolean)(f: => T): T = { @annotation.tailrec def _retry(_intervals: Stream[Int], errors: List[Throwable]): T = { allCatch.either(f) match { case Right(r) => r case Left(e) => if (shouldCatch(e)) { _intervals match { case head #:: tail => Thread.sleep(head) _retry(tail, e :: errors) case _ => throw RetryException(e :: errors) } } else throw e } } _retry(intervals, Nil) } }