При выполнении длительных загрузок с 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);
}
Я делаю что-то в корне неправильно или это ошибка?
Единственные решения, которые я вижу:
- Подсчитайте полученные байты и сравните их с
Content-Length header
.
- Установите время ожидания запроса -1 (неопределенное).
Спасибо за любые предложения.