В настоящее время я реализую автоматический выключатель с Akka-HTTP следующим образом:
def sendMail(entity: MyEntity): ToResponseMarshallable = {
Thread.sleep(5 * 1000)
validateEntity(entity).map[ToResponseMarshallable] {
case (body, subject) if !isEmpty(body, subject) => {
val mailResponse = sendMail(body, subject)
OK -> ProcessedEmailMessage(mailResponse)
}
case _ =>
BadRequest -> s"error: for $entity".toJson
}
} catch {
case e: DeserializationException => HttpResponse(BadRequest).withEntity(HttpEntity(s"error:${e.msg}").withContentType(ContentTypes.`application/json`))
}
}
val maxFailures: Int = 2
val callTimeout: FiniteDuration = 1 second
val resetTimeout: FiniteDuration = 30 seconds
def open: Unit = {
logger.info("Circuit Breaker is open")
}
def close: Unit = {
logger.info("Circuit Breaker is closed")
}
def halfopen: Unit = {
logger.info("Circuit Breaker is half-open, next message goes through")
private lazy val breaker = CircuitBreaker(
system.scheduler,
maxFailures,
callTimeout,
resetTimeout
).onOpen(open).onClose(close).onHalfOpen(halfopen)
def routes: Route = {
logRequestResult("email-service_aggregator_email") {
pathPrefix("v1") {
path("sendmail") {
post {
entity(as[EmailMessage]) { entity =>
complete {
breaker.withCircuitBreaker(Future(sendMail(entity)))
}
}
}
}
}
}
}
Моя проблема в том, что если я использую breaker.withCircuitBreaker(Future(sendMail(entity)))
, автоматический выключатель переходит в разомкнутое состояние, но остальная часть ответа возвращает There was an internal server error
в качестве ответа.
Если вместо этого я использую breaker.withSyncCircuitBreaker(Future(sendMail(entity)))
, то автоматический выключатель никогда не переходит в разомкнутое состояние, но возвращает ожидаемое HttpResponse
Любые мысли о том, как я могу решить эту проблему, чтобы активировать автоматический выключатель, а также вернуть правильный ответ HTTP?
breaker
? - person Pim Verkerk   schedule 01.03.2016onComplete
вместоcomplete
. Директиваcomplete
ожидает, что ответ будет готов немедленно. В вашем случаеwithCircuitBreaker
возвращаетFuture
, поэтомуcomplete
не будет допустимым вариантом. ДирективаonComplete
настроена для работы сFuture
, так что здесь она лучше подходит. Затем внутри обратного вызоваonComplete
вы можете использоватьcomplete
. - person cmbaxter   schedule 01.03.2016