java - PlayWS - 达到请求超时时如何抛出异常?
问题描述
当使用 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(无限期)。
感谢您的任何建议。
解决方案
我认为有些过于复杂了。
您可以从Future
或附加CompletableStage
到Source
。CompletableFuture
Akka Streams 的 API 比(我认为)更强大
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)
推荐阅读
- android - 我的 webview 在默认浏览器中打开网页
- python - torch.nn.conv* 中的 groups 参数如何影响卷积过程?
- javascript - 为什么我不能分配给动态创建的 html 文档的正文?
- javascript - 如何正确地将 Promises 串在一起以进行同步代码执行
- ios - 如何使用 XCode 的 Interface Builder 设计一个很长的 Scrollview
- java - 两个节点之间的减法
- sql - Postgres 子查询 - 如何从子查询创建对象格式的别名
- scheduled-tasks - Windows IOT 任务不在启动时运行(但它在手动命令上运行)
- arrays - 给定一个带有值数组的哈希,如何提取每个键的唯一值的数量?
- youtube-api - 为什么这个来自 Ionic 4 的 httpClient 不起作用?