Skip to content

Instantly share code, notes, and snippets.

@j5ik2o
Forked from xuwei-k/not_tailrec.scala
Created June 26, 2012 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j5ik2o/2998985 to your computer and use it in GitHub Desktop.
Save j5ik2o/2998985 to your computer and use it in GitHub Desktop.
リトライハンドラーの殴り書き
  • List[Class[_]] に catch するべき Class が含まれているか? 」 ではなく、「 catch するべき例外かどうか? 」そのものを表す関数を渡すように変更した
  • 再帰のたびに毎回 List 内の error の数が1づつ増えてるはずなので、 counter のパラメータは List の size から取得するようにして消した
  • retryLimit 超えて例外が発生し続けた場合、結局その例外Listを最後に投げるので、関数内関数の内部で先になげてしまうようにした
  • 最初 not_tailrec.scala の方にしたけど、 try catchは末尾再帰が効かないらしい ので、最終的に allCatch で一度 catch した後 match するようにした
  • allCatch は本当に全部catchするわけではないので、厳密にいうとちょっと動作変わってる
object RetryUtil {
case class RetryException(throwables: List[Throwable]) extends Exception
def retry[T](retryLimit: Int, retryInterval: Int, shouldCatch: Throwable => Boolean)(f: => T): T = {
// @annotation.tailrec
def _retry( errors: List[Throwable], f: => T):T = {
try {
f
} catch {
case e if shouldCatch(e) =>
if (errors.size < retryLimit) {
Thread.sleep(retryInterval)
_retry( e :: errors, f)
} else {
throw RetryException(e :: errors)
}
}
}
_retry( Nil, f)
}
}
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 = {
@annotation.tailrec
def _retry( errors: List[Throwable], f: => T):T = {
allCatch.either(f) match{
case Right(r) => r
case Left(e) =>
if(shouldCatch(e)){
if (errors.size < retryLimit) {
Thread.sleep(retryInterval)
_retry( e :: errors, f)
} else {
throw RetryException(e :: errors)
}
}else throw e
}
}
_retry( Nil, f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment