onComplete
Signature
Description
Evaluates its parameter of type Future[T]
, and once the Future
has been completed, extracts its
result as a value of type Try[T]
and passes it to the inner route.
To handle the Failure
case automatically and only work with the result value, use onSuccess.
To complete with a successful result automatically and just handle the failure result, use completeOrRecoverWith, instead.
Example
def divide(a: Int, b: Int): Future[Int] = Future {
a / b
}
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
}
}
// tests:
Get("/divide/10/2") ~> route ~> check {
responseAs[String] shouldEqual "The result was 5"
}
Get("/divide/10/0") ~> Route.seal(route) ~> check {
status shouldEqual InternalServerError
responseAs[String] shouldEqual "An error occurred: / by zero"
}
def divide(a: Int, b: Int): Future[Int] = Future {
a / b
}
val resetTimeout = 1.second
val breaker = new CircuitBreaker(system.scheduler,
maxFailures = 1,
callTimeout = 5.seconds,
resetTimeout
)
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onCompleteWithBreaker(breaker)(divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
}
}
// tests:
Get("/divide/10/2") ~> route ~> check {
responseAs[String] shouldEqual "The result was 5"
}
Get("/divide/10/0") ~> Route.seal(route) ~> check {
status shouldEqual InternalServerError
responseAs[String] shouldEqual "An error occurred: / by zero"
} // opens the circuit breaker
Get("/divide/10/2") ~> route ~> check {
rejection shouldBe a[CircuitBreakerOpenRejection]
}
Thread.sleep(resetTimeout.toMillis + 200)
Get("/divide/10/2") ~> route ~> check {
responseAs[String] shouldEqual "The result was 5"
}
Contents