Skip to content

Instantly share code, notes, and snippets.

@richashworth
Created August 30, 2018 22:40
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 richashworth/791b05b8c5d65b7182675883d187b759 to your computer and use it in GitHub Desktop.
Save richashworth/791b05b8c5d65b7182675883d187b759 to your computer and use it in GitHub Desktop.
Retry logic implemented with IO monad
import cats.effect.{IO, Timer}
import cats.syntax.applicativeError._
import cats.syntax.apply._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.{FiniteDuration, _}
import scala.math._
// From https://typelevel.org/cats-effect/datatypes/io.html#example-retrying-with-exponential-backoff
def eventually[A](ioa: IO[A], initialDelay: FiniteDuration = 1.second, maxRetries: Int = 10, backOffMultiplier: Int = 1)
(implicit timer: Timer[IO]): IO[A] = {
ioa.handleErrorWith { error =>
if (maxRetries > 0)
IO.sleep(initialDelay) *> eventually(ioa, initialDelay * backOffMultiplier, maxRetries - 1)
else
IO.raiseError(error)
}
}
def gen: IO[Int] = IO {
val x = round(random * 10).intValue()
println(x)
if (x != 2) throw new RuntimeException(s"x was $x")
x
}
def x: IO[Int] = eventually(gen, maxRetries = 5)
x.unsafeRunSync() // will eventually produce 2 or throw the exception if retries are exhausted
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment