#scala #post #akka #akka-http
#scala #Публикация #akka #akka-http
Вопрос:
Я выполняю POST-запрос со следующим API на стороне HTTP-запроса akka.
Http().singleRequest(....)
Я обнаружил, что akka http для post не поддерживает повторные попытки.
// max-retries = 3 // AKKA http default value is 5, and it doesn't work for POST request
Тогда каков был бы наилучший подход для выполнения повторной попытки в случае POST-запроса.
Комментарии:
1. Хорошо, значит, он повторяет попытку автоматически, если происходит внутренний сбой? Но я обнаружил эту проблему здесь, что post не повторяет попыток: github.com/akka/akka-http/issues/2609
2. Вы правы: повторная попытка запроса
Ответ №1:
Вы можете попробовать что-то подобное, основанное на akka.pattern.retry
object Example {
case class RetryConfig(attempts: Int, minBackoff: FiniteDuration, maxBackoff: FiniteDuration, randomFactor: Double)
class SingleRequestClient(implicit system: ActorSystem) {
def request(request: HttpRequest): Future[HttpResponse] = {
Http().singleRequest(request)
}
}
object SingleRequestClient {
def apply(implicit system: ActorSystem): SingleRequestClient = {
new SingleRequestClient
}
def apply(config: RetryConfig)(implicit system: ActorSystem, ex: ExecutionContext): SingleRequestClient = {
new SingleRequestClient {
override def request(request: HttpRequest): Future[HttpResponse] = {
akka.pattern.retry(
attempt = () => super.request(request),
attempts = config.attempts,
minBackoff = config.minBackoff,
maxBackoff = config.maxBackoff,
randomFactor = config.randomFactor
)(ex, system.scheduler)
}
}
}
}
}
Кроме того, вы должны установить max-retries равным 0.
Ofc это работает только с Future.failed, поэтому, если вы хотите повторить запрос при статусе != 200, вы можете немного изменить базовую реализацию
class SingleRequestClient(implicit system: ActorSystem, ex: ExecutionContext) {
def request(request: HttpRequest): Future[HttpResponse] = {
Http().singleRequest(request).map {
case res: HttpResponse if res.status.isSuccess => res
case res: HttpResponse if res.status.isFailure =>
throw new Exception(s"Cannot process request dou to ${res.status.intValue} status")
}
}
}
Комментарии:
1. «Кроме того, вы должны установить max-retries равным 0». Почему? Потому что я могу использовать идемпотентный запрос в SingleRequestClient#request?
2. потому что у вас уже есть пользовательские повторные попытки, поэтому вам не нужны повторные попытки akka для запросов GET