Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create version for exponential backoff with max capped delay #187

Open
Ssstlis opened this issue Mar 30, 2020 · 3 comments · May be fixed by #193
Open

Create version for exponential backoff with max capped delay #187

Ssstlis opened this issue Mar 30, 2020 · 3 comments · May be fixed by #193

Comments

@Ssstlis
Copy link

Ssstlis commented Mar 30, 2020

Similar to akka i wanna have ability to create exponential backoff retry policy with max capped delay just for keep logical delay, not like 10 minutes.
I can create PR by myself if you don't mind :)

@cb372
Copy link
Owner

cb372 commented Mar 31, 2020

I'm not sure what you mean by "logical delay". Do you have a link to the Akka docs for this feature? Or some sample code to show what it looks like in Akka?

@Ssstlis
Copy link
Author

Ssstlis commented Mar 31, 2020

In akka we have this functionality:

RestartSource.onFailuresWithBackoff(
      minBackoff = 3.seconds,
      maxBackoff = 30.seconds,
      randomFactor = 0.2,
      maxRestarts = -1
    )(() => YourStream)

Link to api docs

When we migrate to fs2 i wrote this policy for reproduce this behavior in cats-retry:

  def exponentialRandomBackoff[M[_] : Applicative](
    minBackoff: FiniteDuration,
    maxBackoff: FiniteDuration,
    randomFactor: Double,
    maxRestarts: Int
  ): RetryPolicy[M] =
    RetryPolicy.liftWithShow[M]({
      status =>
        if (maxRestarts == -1 || status.retriesSoFar < maxRestarts) {
          val delay =
            if (status.previousDelay.exists(_ >= maxBackoff))
              maxBackoff
            else {
              //Copy-paste from RetryPolicies.safeMultiply
              val durationNanos = BigInt(minBackoff.toNanos)
              val resultNanos = durationNanos * BigInt(Math.pow(2, status.retriesSoFar.toDouble).toLong)
              val safeResultNanos = resultNanos min BigInt(Long.MaxValue)
              val duration_ = (FiniteDuration(safeResultNanos.toLong, TimeUnit.NANOSECONDS) *
                (1.0 + Random.nextDouble() * randomFactor)) min maxBackoff

              FiniteDuration(duration_.toNanos, TimeUnit.NANOSECONDS)
            }
          DelayAndRetry(delay)
        } else
          GiveUp
    }, show"exponentialRandomBackoff(minBackoff=$minBackoff, maxBackoff=$maxBackoff, randomFactor=$randomFactor, maxRestarts=$maxRestarts)")

Also i reference path of this code issue in #188

@Ssstlis
Copy link
Author

Ssstlis commented Mar 31, 2020

I rewrite this example with built-in functions:

  def exponentialRandomBackoff[M[_] : Applicative](
    minBackoff: FiniteDuration,
    maxBackoff: FiniteDuration,
    randomFactor: Double,
    maxRestarts: Int
  ): RetryPolicy[M] =
    RetryPolicy
      .withShow[M](
        { status =>
          RetryPolicies.exponentialBackoff[M](minBackoff).decideNextRetry(status).map {
            case GiveUp => GiveUp
            case DelayAndRetry(delay) =>
              val nextDelay = delay * (1.0 + Random.nextDouble() * randomFactor)
              DelayAndRetry(FiniteDuration(nextDelay.toNanos, TimeUnit.NANOSECONDS))
          }
        },
        show"exponentialRandomBackoff(minBackoff=$minBackoff, randomFactor=$randomFactor)"
      )
      .meet(RetryPolicies.constantDelay(maxBackoff))
      .join(
        if (maxRestarts == -1)
          RetryPolicies.constantDelay[M](Duration.Zero)
        else
          RetryPolicies.limitRetries[M](maxRestarts)
      )

So i think that we can put something like this in lib would be helpful for devs who migrate from akka-streams to fs2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants