Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2017
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.66 KB | None | 0 0
  1. import java.util.{Timer, TimerTask}
  2. import org.joda.time.Duration
  3. import scala.concurrent.{Await, ExecutionContext, Future, Promise}
  4. import scala.concurrent.duration.Duration.Inf
  5. import scala.math.min
  6. import scala.util.Random
  7.  
  8. def withBackoff[A](maxRetry: Int,
  9. baseDelay: Duration,
  10. maxBackoffTime: Duration)
  11. (f: => Future[A])
  12. (implicit executionContext: ExecutionContext,
  13. random: Random,
  14. timer: Timer): Future[A] = {
  15. val maxMillis = maxBackoffTime.getMillis.toInt
  16. val promise = Promise[A]
  17.  
  18. def task(retry: Int, delay: Int)
  19. (implicit executionContext: ExecutionContext): TimerTask =
  20. new TimerTask {
  21. def run() {
  22. val future = f
  23.  
  24. future.onSuccess { case result => promise.success(result) }
  25.  
  26. future.onFailure {
  27. case _ if retry > 0 =>
  28. val jitter = random.nextInt(min(delay, maxMillis)) + 1
  29.  
  30. println(s"Retrying in ${jitter}ms")
  31. timer.schedule(task(retry - 1, delay << 1), jitter)
  32.  
  33. case exception =>
  34. promise.failure(exception)
  35. }
  36. }
  37. }
  38.  
  39. task(maxRetry, baseDelay.getMillis.toInt).run()
  40.  
  41. promise.future
  42. }
  43.  
  44.  
  45. def flaky(probability: Int)(implicit random: Random) = {
  46. val number = random.nextInt(probability)
  47.  
  48. if (number == 0)
  49. Future.successful(number)
  50. else
  51. Future.failed(new RuntimeException(s"It was ${number}"))
  52. }
  53.  
  54.  
  55. import scala.concurrent.ExecutionContext.Implicits.global
  56.  
  57. implicit val random = Random
  58. implicit val timer: Timer = new Timer(true)
  59.  
  60. Await.result(withBackoff(10, new Duration(500), new Duration(20000))(flaky(5)), Inf)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement