onComplete

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