Я в настоящее время осуществляет автоматический выключатель с Акка-HTTP следующим образом:Автоматический выключатель для Scala и Акка-клиента остальное обслуживание
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'? –
Конечно, я отредактировал это –
Вам нужно использовать 'onComplete' вместо' complete'. Директива 'complete' ожидает, что ответ будет готов к немедленному завершению. В вашем случае 'withCircuitBreaker' возвращает' Future', поэтому 'complete' не будет допустимым вариантом. Директива 'onComplete' настроена для работы с« Будущим », поэтому она лучше подходит. Затем в обратном вызове 'onComplete' вы можете использовать' complete'. – cmbaxter