- 「
List[Class[_]]
に catch するべき Class が含まれているか? 」 ではなく、「 catch するべき例外かどうか? 」そのものを表す関数を渡すように変更した - 再帰のたびに毎回 List 内の error の数が1づつ増えてるはずなので、
counter
のパラメータは List の size から取得するようにして消した retryLimit
超えて例外が発生し続けた場合、結局その例外Listを最後に投げるので、関数内関数の内部で先になげてしまうようにした- 最初
not_tailrec.scala
の方にしたけど、 try catchは末尾再帰が効かないらしい ので、最終的に allCatch で一度 catch した後 match するようにした- 将来のversion(おそらく2.10.1以降?)ではこの制限緩和されるかも scala/scala#1711
- allCatch は本当に全部catchするわけではないので、厳密にいうとちょっと動作変わってる
-
-
Save xuwei-k/2996927 to your computer and use it in GitHub Desktop.
リトライハンドラーの殴り書き
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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