4

I am doing a POST request with the following akka http request side api.

   Http().singleRequest(....)

I found that akka http for post doesn't support retries.

// max-retries = 3 // AKKA http default value is 5, and it doesn't work for POST request

Then what would be the best approach for doing a retry in case of POST request .

supernatural
  • 1,107
  • 11
  • 34
  • Ok, so it retries automatically if it fails internally ? But i found this issue here that post doesnt retries: https://github.com/akka/akka-http/issues/2609 – supernatural Dec 27 '20 at 14:01
  • You are right: [Retrying a Request](https://doc.akka.io/docs/akka-http/current/client-side/host-level.html#retrying-a-request) – Tomer Shetah Dec 27 '20 at 15:10

1 Answers1

4

You can try something like this, based on 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)
    }
      }
    }
  }
}

Additionally, You should set max-retries to 0.

Ofc it works only with Future.failed so if you want to retry request on status != 200, you can change the basic implementation a little

  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")
      }
    }
  }
mForest
  • 88
  • 11