scala/basic
scala 에서 retry 구현하기
wefree
2021. 11. 25. 18:11
문제
cats-effect 나 zio 등의 functional library 를 사용하면, 이미 구현되어 있는 retry 를 쉽게 사용할 수 있다. 혹은 retry library 를 활용할 수도 있다. 간단하게 쓸수 있도록 scala 표준 라이브러리만을 사용해 retry 를 구현해 보자. stackoverflow 를 참고할 수 있다.
코드
import scala.annotation.tailrec
import scala.util.{Failure, Success, Try}
object Util {
@tailrec
def retry[T](n: Int)(f: => T): Try[T] =
if (n < 0) {
Failure(new Exception(s"$n must be greater or equal to 0"))
} else if (n == 0) {
Try(f)
} else {
Try(f) match {
case Success(value) => Success(value)
case Failure(_) => if (n == 1) Try(f) else retry(n - 1)(f)
}
}
}
AI 코드
import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.duration._
import scala.util.{Failure, Success}
import java.util.concurrent.Executors
object RetryUtil {
def retry[T](block: => Future[T], maxRetries: Int, delay: FiniteDuration)
(implicit ec: ExecutionContext): Future[T] = {
block.recoverWith {
case _ if maxRetries > 0 =>
println(s"Retrying... attempts left: $maxRetries")
Thread.sleep(delay.toMillis)
retry(block, maxRetries - 1, delay)
}
}
}
// 사용 예제
object Main extends App {
implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(4))
def unreliableOperation: Future[Int] = Future {
val random = scala.util.Random
val value = random.nextInt(10)
if (value < 8) throw new RuntimeException("Failed operation")
else value
}
val result = RetryUtil.retry(unreliableOperation, 5, 2.seconds)
result.onComplete {
case Success(value) => println(s"Operation succeeded with value: $value")
case Failure(exception) => println(s"Operation failed after retries: ${exception.getMessage}")
}
}