java - 调用函数直到发生异常的 Guava 重试器
问题描述
假设我有一些这样的代码:
public void deleteResource(UUID resourceId) {
deleteFromDb();
deleteFromALotOfOtherPlaces(); // Takes a long time!
}
public DescribeResourceResult describeResource(UUID resourceId) throws ResourceNotFoundException {
return getResourceDescription(resourceId);
}
不幸的是,删除并不表示它已完成。验证删除是否完成的唯一方法是调用describeResource
which 将在资源已被删除时抛出异常。
我想写一个重试器,它会反复调用describeResrouce
直到 aResourceNotFoundException
发生。我怎样才能做到这一点?
这是我到目前为止所拥有的:
final Retryer<ResourceNotFoundException> deleteResourceRetryer = RetryerBuilder.<ResourceNotFoundException>newBuilder()
.withWaitStrategy(WaitStrategies.fixedWait(500, TimeUnit.MILLISECONDS))
.withStopStrategy(StopStrategies.stopAfterDelay(10, TimeUnit.SECONDS))
.build();
// Error: Bad return type in lambda expression: DescribeResourceResult cannot be converted to ResourceNotFoundException
deleteResourceRetryer.call(() -> describeResource(resourceId));
谢谢!
解决方案
我对 Guava 不太熟悉Retryer
,因此经过短暂调查后,我找不到现成的StopStrategy
,所以我的建议是自己实施
static class OnResourceNotFoundExceptionStopStrategy implements StopStrategy {
@Override
public boolean shouldStop(Attempt attempt) {
if (attempt.hasException()
&& attempt.getExceptionCause() instanceof ResourceNotFoundException) {
return true;
}
return false;
}
}
使用该策略重试将在您捕获时停止ResourceNotFoundException
。之后修复类型并正确定义Retryer
final Retryer<DescribeResourceResult> deleteResourceRetryer = RetryerBuilder
.<DescribeResourceResult>newBuilder()
.retryIfResult(Predicates.notNull())
.withWaitStrategy(WaitStrategies.fixedWait(500, TimeUnit.MILLISECONDS))
.withStopStrategy(new OnResourceNotFoundExceptionStopStrategy())
.build();
最后,开始重试
try {
deleteResourceRetryer.call(() -> describeResource(resourceId));
} catch (ExecutionException e) {
// should not happens, because you will retry if any exception rather
// than ResourceNotFoundException raised in your describeResource method
} catch (RetryException e) {
// should not happens, because my implementation of StopStrategy
// (as it looks in this example) is effectively infinite, until target exception.
// For sure you're free to override it to anything you want
}
希望能帮助到你!
推荐阅读
- c++ - OpenBLAS 只为一个例程设置线程数
- javascript - 使用(Javascript)动态切换到不同的firebase项目应用程序
- python - 熊猫:尝试为数据框列表连续编辑数据
- neo4j - 如何使用可变长度关系和每个级别的过滤器查询 Neo4j N 级别的深度
- angular - Angular 8 和材料缺失
- laravel - 路由参数和对象属性值相同,但不相等
- sql - 将产品从多条记录的订单数据返回到列
- google-app-maker - 使用“或”在 appmaker 中构建查询
- javascript - 为什么 document.body.addEventListener 事件在 document.addEventListener 之前运行?
- java - 如何在 Java 8 + hibernate 验证器中为通用类型使用自定义注释?