根据结果重试方法(而不是异常)

2022-09-04 03:39:31

我有一个具有以下签名的方法:

public Optional<String> doSomething() {
    ...
}

如果我得到一个空,我想重试此方法,只有在3次后返回空。OptionalOptional

我查看并找到了弹簧注释,但它似乎仅适用于异常。Retryable

如果可能的话,我想为此使用一个库,并避免:

  • 创建并引发异常。
  • 自己编写逻辑。

答案 1

我一直在重试中使用故障安全构建。您可以根据谓词和异常重试。

您的代码将如下所示:

    private Optional<String> doSomethingWithRetry() {
        RetryPolicy<Optional> retryPolicy = new RetryPolicy<Optional>()
                .withMaxAttempts(3)
                .handleResultIf(result -> {
                    System.out.println("predicate");
                    return !result.isPresent();
                });

        return Failsafe
                .with(retryPolicy)
                .onSuccess(response -> System.out.println("ok"))
                .onFailure(response -> System.out.println("no ok"))
                .get(() -> doSomething());
    }

    private Optional<String> doSomething() {
         return Optional.of("result");
    }

如果可选选项不为空,则输出为:

predicate
ok

否则看起来像:

predicate
predicate
predicate
no ok

答案 2

@Retryable(和底层的)纯粹基于例外。RetryTemplate

您可以子类 ,覆盖以检查返回值。RetryTemplatedoExecute()

您可能必须复制该方法中的大部分代码;它并不是真正设计用于覆盖呼叫而设计的。retryCallback.doWithRetry()

可以在 中使用自定义(在属性中指定)。RetryTemplateRetryOperationsInterceptor@Retryableinterceptor

编辑

当前代码如下所示...RetryTemplate

while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {

    try {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Retry: count=" + context.getRetryCount());
        }
        // Reset the last exception, so if we are successful
        // the close interceptors will not think we failed...
        lastException = null;
        return retryCallback.doWithRetry(context);
    }
    catch (Throwable e) {

        lastException = e;

        try {
            registerThrowable(retryPolicy, state, context, e);
        }
        catch (Exception ex) {
            throw new TerminatedRetryException("Could not register throwable",
                    ex);
        }
        finally {
            doOnErrorInterceptors(retryCallback, context, e);
        }

         ... 

    }

您需要将其更改为类似...

while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {

    try {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Retry: count=" + context.getRetryCount());
        }
        // Reset the last exception, so if we are successful
        // the close interceptors will not think we failed...
        lastException = null;
        T result = retryCallback.doWithRetry(context);
        if (((Optional<String>) result).get() == null) {

            try {
                registerThrowable(retryPolicy, state, context, someDummyException);
            }
            catch (Exception ex) {
                throw new TerminatedRetryException("Could not register throwable",
                        ex);
            }
            finally {
                doOnErrorInterceptors(retryCallback, context, e);
            }

            ...
        }
        else {
            return result;
        }
    }
    catch (Throwable e) {

       ...

    }

哪里是欺骗上下文以增加计数器。它可以是一个字段,只需创建一次。someDummyExceptionstatic


推荐