Как добавить повторные попытки к POST-запросу в akka http?

#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