2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2019-01-02 18:55:26 +08:00
|
|
|
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
|
2018-03-26 14:56:20 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.pattern
|
|
|
|
|
|
|
|
|
|
import akka.actor.Scheduler
|
|
|
|
|
|
|
|
|
|
import language.postfixOps
|
|
|
|
|
import akka.testkit.AkkaSpec
|
|
|
|
|
|
|
|
|
|
import scala.concurrent.{ Await, ExecutionContextExecutor, Future }
|
|
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
|
|
|
|
|
class RetrySpec extends AkkaSpec with RetrySupport {
|
|
|
|
|
implicit val ec: ExecutionContextExecutor = system.dispatcher
|
|
|
|
|
implicit val scheduler: Scheduler = system.scheduler
|
|
|
|
|
|
|
|
|
|
"pattern.retry" must {
|
|
|
|
|
"run a successful Future immediately" in {
|
|
|
|
|
val retried = retry(
|
2019-02-09 15:25:39 +01:00
|
|
|
() => Future.successful(5),
|
2018-03-26 14:56:20 +03:00
|
|
|
5,
|
|
|
|
|
1 second
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
within(3 seconds) {
|
|
|
|
|
Await.result(retried, remaining) should ===(5)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"run a successful Future only once" in {
|
|
|
|
|
@volatile var counter = 0
|
|
|
|
|
val retried = retry(
|
2019-02-09 15:25:39 +01:00
|
|
|
() => Future.successful({
|
2018-03-26 14:56:20 +03:00
|
|
|
counter += 1
|
|
|
|
|
counter
|
|
|
|
|
}),
|
|
|
|
|
5,
|
|
|
|
|
1 second
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
within(3 seconds) {
|
|
|
|
|
Await.result(retried, remaining) should ===(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"eventually return a failure for a Future that will never succeed" in {
|
|
|
|
|
val retried = retry(
|
2019-02-09 15:25:39 +01:00
|
|
|
() => Future.failed(new IllegalStateException("Mexico")),
|
2018-03-26 14:56:20 +03:00
|
|
|
5,
|
|
|
|
|
100 milliseconds
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
within(3 second) {
|
|
|
|
|
intercept[IllegalStateException] { Await.result(retried, remaining) }.getMessage should ===("Mexico")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"return a success for a Future that succeeds eventually" in {
|
|
|
|
|
@volatile var failCount = 0
|
|
|
|
|
|
|
|
|
|
def attempt() = {
|
|
|
|
|
if (failCount < 5) {
|
|
|
|
|
failCount += 1
|
|
|
|
|
Future.failed(new IllegalStateException(failCount.toString))
|
|
|
|
|
} else Future.successful(5)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val retried = retry(
|
2019-02-09 15:25:39 +01:00
|
|
|
() => attempt,
|
2018-03-26 14:56:20 +03:00
|
|
|
10,
|
|
|
|
|
100 milliseconds
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
within(3 seconds) {
|
|
|
|
|
Await.result(retried, remaining) should ===(5)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"return a failure for a Future that would have succeeded but retires were exhausted" in {
|
|
|
|
|
@volatile var failCount = 0
|
|
|
|
|
|
|
|
|
|
def attempt() = {
|
|
|
|
|
if (failCount < 10) {
|
|
|
|
|
failCount += 1
|
|
|
|
|
Future.failed(new IllegalStateException(failCount.toString))
|
|
|
|
|
} else Future.successful(5)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val retried = retry(
|
2019-02-09 15:25:39 +01:00
|
|
|
() => attempt,
|
2018-03-26 14:56:20 +03:00
|
|
|
5,
|
|
|
|
|
100 milliseconds
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
within(3 seconds) {
|
|
|
|
|
intercept[IllegalStateException] { Await.result(retried, remaining) }.getMessage should ===("6")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|