说我有一些这样的代码:
public void deleteResource(UUID resourceId) {
deleteFromDb();
deleteFromALotOfOtherPlaces(); // Takes a long time!
}
public DescribeResourceResult describeResource(UUID resourceId) throws ResourceNotFoundException {
return getResourceDescription(resourceId);
}
不幸的是,删除操作并不表示已完成删除。验证删除是否完成的唯一方法是调用describeResource
,如果资源已删除,它将引发异常。
我想编写一个重试器,该重试器将反复调用describeResrouce
,直到发生ResourceNotFoundException
为止。我该怎么办?
这是我到目前为止所拥有的:
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));
谢谢!
答案 0 :(得分:1)
我对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
}
希望有帮助!
答案 1 :(得分:0)
使用Failsafe:
RetryPolicy<Object> retryPolicy = new RetryPolicy<>()
.abortOn(ResourceNotFoundException.class);
.withDelay(Duration.ofMillis(500))
.withMaxDuration(Duration.ofSeconds(10));
Failsafe.with(retryPolicy).get(() -> getResourceDescription(resourceId));