调用函数直到发生异常的 Guava 重试器
Guava retryer that calls a function until an exception occurs
假设我有这样的代码:
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));
谢谢!
我对 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
}
希望对您有所帮助!
使用Failsafe:
RetryPolicy<Object> retryPolicy = new RetryPolicy<>()
.abortOn(ResourceNotFoundException.class);
.withDelay(Duration.ofMillis(500))
.withMaxDuration(Duration.ofSeconds(10));
Failsafe.with(retryPolicy).get(() -> getResourceDescription(resourceId));
假设我有这样的代码:
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));
谢谢!
我对 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
}
希望对您有所帮助!
使用Failsafe:
RetryPolicy<Object> retryPolicy = new RetryPolicy<>()
.abortOn(ResourceNotFoundException.class);
.withDelay(Duration.ofMillis(500))
.withMaxDuration(Duration.ofSeconds(10));
Failsafe.with(retryPolicy).get(() -> getResourceDescription(resourceId));