PlayWS - Как вызвать исключение при достижении времени ожидания запроса? - PullRequest
0 голосов
/ 08 ноября 2018

При выполнении длительных загрузок с PlayWS, использующей CompletableFuture, они иногда достигают определенного времени ожидания запроса. Когда это происходит, PlayWS, похоже, не выдает исключение (по крайней мере, в моей конфигурации), поэтому загрузка не может быть помечена как неудачная и обрабатывается, хотя данные повреждены.

Прошу прощения за эту мерзость кода:

final CompletionStage<WSResponse> futureResponse = this.playWS.client
        .url(importSource.getDownloadUrl())
        .setMethod(HttpMethod.GET)
        .setRequestTimeout(Duration.ofSeconds(5)) // When the timeout is reached, the download gets canceled
        .stream();

try {
    futureResponse
            .thenAccept(res -> {
                try (OutputStream outputStream = Files.newOutputStream(file.toPath())) {
                    final Source<ByteString, ?> responseBody = res.getBodyAsSource();
                    final Sink<ByteString, CompletionStage<Done>> outputWriter =
                            Sink.foreach(bytes -> {
                                outputStream.write(bytes.toArray());
                            });
                    responseBody
                            .runWith(outputWriter, this.playWS.materializer)
                            .whenComplete((value, error) -> {
                                System.out.println("VALUE: "+value); // == "Done"
                                System.out.println("Error: "+error); // == null
                            })
                            .exceptionally(exception -> {
                                throw new IllegalStateException("Download failed for: " + importSource.getDownloadUrl(), exception);
                            })
                            .toCompletableFuture().join();
                } catch (final IOException e) {
                    throw new IllegalStateException("Couldn't open or write to OutputStream.", e);
                }
            })
            .exceptionally(exception -> {
                throw new IllegalStateException("Download failed for: " + importSource.getDownloadUrl(), exception);
            })
            .toCompletableFuture().get();
} catch (InterruptedException | ExecutionException e) {
    throw new IllegalStateException("Couldn't complete CompletableFuture.", e);
}

Я делаю что-то в корне неправильно или это ошибка?

Единственные решения, которые я вижу:

  1. Подсчитайте полученные байты и сравните их с Content-Length header.
  2. Установите время ожидания запроса -1 (неопределенное).

Спасибо за любые предложения.

1 Ответ

0 голосов
/ 11 ноября 2018

Я думаю, что есть некоторое чрезмерное осложнение.

Вы можете просто прикрепить от Future или CompletableStage к Source.У Akka Streams более надежный API, чем CompletableFuture (мое мнение)

final CompletionStage<WSResponse> futureResponse = this.playWS.client
        .url(importSource.getDownloadUrl())
        .setMethod(HttpMethod.GET)
        .setRequestTimeout(Duration.ofSeconds(5)) 
        .stream();

Source<WSResponse> source = Source.fromCompletableStage(futureResponse);
source.map(...).filter(...).recover(...).runforeach(..., playWS.materializer)
...