【发布时间】:2021-07-29 04:53:37
【问题描述】:
很难对后台任务进行可靠的重试,该任务会向邮件服务发送请求以获取最新的电子邮件。成功接收电子邮件后,应在thenAccept() 块中继续执行 - 保留电子邮件,但是如果发生异常,我必须重新运行邮件检索,直到成功尝试,成功后应该保留邮件并停止。如果我做错了,请看看并提出建议。
private void retrieveMailsAsync(User user) {
CompletableFuture.supplyAsync(() -> {
try {
return mailService.getEmails(user.getName(), user.getPassword());
} catch (InvalidAuthentication | TimeoutException | BadGatewayException e) {
throw new CompletionException(e);
}
}).thenAccept(email -> {
mailService.persist(email);
}).exceptionally(ex -> {
log.log(Level.SEVERE, "Exception retrieveMailsAsync emails, Retrying retrieveMailsAsync:: ", ex.getCause());
retrieveMailsAsync(user);
return null;
});
}
PS 也请看看我是如何处理检查异常,将其包装到 CompletionException 并重新抛出 - 这里的主要思想是在一个 exceptionally() 块中处理所有异常(定义检查和运行时)而不是记录它们在 catch 块中并返回 null。
提前感谢大家,希望我没有做一些愚蠢的事情,或者至少已经有适用于 Java 8 的可靠解决方案。
【问题讨论】:
-
这是独立代码还是在spring等一些框架下,有了spring有更好的重试方式吗?也让我们知道是什么问题,您是否异常不重试活动?
-
如果您至少有 jdk-12,这在某种程度上很容易,对吗?
-
不幸的是,它是没有任何框架的普通 Java 8((这里的问题是,以这种方式处理重试是否是有效的案例 - 从异常块递归?
-
也许我理解错了,但是如果你想重试直到成功,为什么你首先抛出完成异常?您可以在运行部分循环,直到您毫无例外地离开。
-
@daniu,很抱歉造成混淆。问题是 mailService 抛出了我必须处理的检查异常,所以我将它们包装在运行时 CompletionException 中,这样我试图在一个地方收集异常处理登录 - 例如在 exceptionly() 块中。否则,我必须在 catch{} 块中处理检查的异常和重试逻辑一次,在异常块中处理其他未经检查的 + 重试逻辑。但是我的解决方案在一个地方积累了这个逻辑。希望如此)
标签: java recursion exception completable-future