Skip to content

Commit

Permalink
Add support for schedules with an environment requirement to Retry (#42)
Browse files Browse the repository at this point in the history
* Add support for schedules with an environment requirement

* Fix
  • Loading branch information
svroonland authored Sep 30, 2020
1 parent ffbfa5e commit 7cf5e1d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
39 changes: 32 additions & 7 deletions rezilience/shared/src/main/scala/nl/vroste/rezilience/Retry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,41 @@ object Retry {
zio.Schedule.recurWhile(pf.isDefinedAt) && schedule
}

def make[E](schedule: Schedule[Any, E, Any]): ZManaged[Clock, Nothing, Retry[E]] =
ZManaged.environment[Clock].map(RetryImpl(_, schedule))
/**
* Create a Retry from a ZIO Schedule
* @param schedule
* @tparam R
* @tparam E
* @return
*/
def make[R, E](schedule: Schedule[R, E, Any]): ZManaged[Clock with R, Nothing, Retry[E]] =
ZManaged.environment[Clock with R].map(RetryImpl(_, schedule))

/**
* Create a Retry policy with exponential backoff
*
* @param min Minimum retry backoff delay
* @param max Maximum retry backoff delay
* @param factor Factor with which delays increase
* @return
*/
def make(
min: Duration = 1.second,
max: Duration = 1.minute,
factor: Double = 2.0
): ZManaged[Clock, Nothing, Retry[Any]] =
ZManaged.environment[Clock].map(RetryImpl(_, Schedule.exponentialBackoff(min, max, factor)))

private case class RetryImpl[-E](clock: Clock, schedule: Schedule[Any, E, Any]) extends Retry[E] {
private case class RetryImpl[-E, ScheduleEnv](
scheduleEnv: Clock with ScheduleEnv,
schedule: Schedule[ScheduleEnv, E, Any]
) extends Retry[E] {
override def apply[R, E1 <: E, A](f: ZIO[R, E1, A]): ZIO[R, E1, A] =
ZIO.environment[R].flatMap(env => f.provide(env).retry(schedule).provide(clock))
ZIO.environment[R].flatMap(env => f.provide(env).retry(schedule).provide(scheduleEnv))

override def widen[E2](pf: PartialFunction[E2, E]): Retry[E2] = RetryImpl[E2](
clock,
(zio.Schedule.stop ||| schedule).contramap[Any, E2] { e2 =>
override def widen[E2](pf: PartialFunction[E2, E]): Retry[E2] = RetryImpl[E2, ScheduleEnv](
scheduleEnv,
(zio.Schedule.stop ||| schedule).contramap[ScheduleEnv, E2] { e2 =>
pf.andThen(Right.apply[E2, E](_)).applyOrElse(e2, Left.apply[E2, E](_))
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object RetrySpec extends DefaultRunnableSpec {
override def spec = suite("Retry")(
testM("widen should not retry unmatched errors") {
Retry
.make[Throwable](Retry.Schedule.exponentialBackoff(1.second, 2.seconds))
.make(Retry.Schedule.exponentialBackoff(1.second, 2.seconds))
.map(_.widen(Policy.unwrap[Throwable]))
.use { retry =>
for {
Expand Down

0 comments on commit 7cf5e1d

Please sign in to comment.