Элегантная обработка ошибок с помощью клиента Scala sttp

#scala #sttp

Вопрос:

Я использую клиент scala sttp и, в частности, использую серверную часть Monix, и у меня есть следующий код:

 def httpTask(href: String): Task[HttpBinaryResponse] = {
  val request = basicRequest
    .get(uri"$href")

  AsyncHttpClientMonixBackend
    .resource()
    .use { backend =>
      request.send(backend).map {
        response: Response[Either[String, String]] =>
          println(s"For URL: $href >> Got response code: ${response.code}")
          HttpBinaryResponse(
            href,
            response.code.isSuccess,
            response.headers.map(elem => (elem.name, elem.value)))
      }
    }
}
 

У меня есть набор URL-адресов, которые я запускаю с помощью этого метода:

 hrefs.toSet.flatten.filter(_.startsWith("http")).map(httpTask) // Set[Task[HttpBinaryResponse]] 
 

В моей функции вызывающего абонента я затем выполняю задачу:

 val taskSeq = appBindings.httpService.parse(parserFilter)
val chunks = taskSeq.sliding(30, 30).toSeq
val batchedTasks = chunks.map(chunk => Task.parSequence(chunk))
val allBatches = Task.sequence(batchedTasks).map(_.flatten)
 

Затем я сопоставляю шаблон с материализованным типом и возвращаю, но то, что я хочу здесь, — это не просто успех и неудача, но я хотел бы иметь оба значения сразу:

 allBatches.runToFuture.materialize.map {
          case Success(elem) =>
            Ok(
              Json
                .obj("status" -> "Ok", "URL size" -> s"${elem.size}")
            ).enableCors
          case Failure(err) =>
            Ok(
              Json
                .obj("status" -> "error", "message" -> s"${err.getMessage}")
            ).enableCors
        }
 

Мне нужно получить список URL-адресов с соответствующим сообщением об успехе или ошибке. При таком подходе к тому, что у меня есть, я получаю только одно из них, что очевидно, поскольку я соответствую шаблону. Как я могу собрать как Успех, так и Неудачу?

Комментарии:

1. Что это за тип elem в конце? Разве это не список всех ваших HttpBinaryResponse, и вы можете просмотреть их, чтобы подсчитать ошибки и успехи?

2. Set[Task[HttpBinaryResponse]] это странно, потому что нет никакого смысла equals для Task . Я думаю, что вы хотите .distinct указать свои входные URL-адреса , но все равно сохраните их Seq , в конечном итоге Seq[Task[HttpBinaryResponse]]

3. Установить значение Seq — это не моя забота! Когда серверная часть выходит из строя для определенного URL-адреса, я оказываюсь в случае сбоя, и я не могу сделать то, что хочу, а именно объединить как неудачу, так и успех.

4. Я думал, что когда БЕ терпит неудачу, ты получаешь Response(Left(errormessage)) . Но если это действительно не удается, вы можете восстановить неудачную задачу и изменить ее, чтобы вернуть HttpBinaryResponse со статусом ошибки (или перенести все это в другое Either ). Вы определенно должны предотвратить сбой задачи, иначе весь пакет завершится неудачей, и в конце вы получите только один сбой. Тебе нужно закончить с Success(Seq(goodOrBad))

5. Не могли бы вы, пожалуйста, опубликовать ответ?