重试/重复延迟不在RxJava2中工作

时间:2017-08-27 18:11:01

标签: rx-java rx-java2

我正在升级到rxjava2,我们有代码来从服务器轮询数据,代码处理在网络问题时重试延迟。但是,当我尝试迁移到rxjava2时,代码停止工作。 以下是Rxjava1的代码,其工作正常,基本上遵循此http://blog.danlew.net/2015/03/02/dont-break-the-chain/和此https://medium.com/@v.danylo/server-polling-and-retrying-failed-operations-with-retrofit-and-rxjava-8bcc7e641a5a

.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
                @Override
                public Observable<?> call(final Observable<? extends Throwable> observable) {
                    // wrap a flatmap here so that i can check the exception type
                    return observable.flatMap(new Func1<Throwable, Observable<?>>() {
                        @Override
                        public Observable<?> call(Throwable throwable) {
                            mThrowable = throwable;
                            if (throwable instanceof IOException) {
                                return observable.compose(timerWithRetries());
                            } else {
                                // for other errors, call onError and exit
                                return Observable.error(throwable);
                            }
                        }
                    });
                }
            })



private <T> Observable.Transformer<T, Long> timerWithRetries() {
    return new Observable.Transformer<T, Long>() {

        @Override
        public Observable<Long> call(Observable<T> observable) {
            return observable
                    .zipWith(Observable.range(COUNTER_START, MAX_RETRIES + 1),
                            new Func2<T, Integer, Integer>() {
                                @Override
                                public Integer call(T t, Integer repeatAttempt) {
                                    return repeatAttempt;
                                }
                            })
                    .flatMap(new Func1<Integer, Observable<Long>>() {
                        @Override
                        public Observable<Long> call(Integer repeatAttempt) {
                            if (repeatAttempt == MAX_RETRIES + 1) {
                                if (mThrowable instanceof IOException) {
                                  // Custom Exception
                                   throw new Exception();
                                }
                            }
                            // increase the waiting time
                            return Observable.timer(repeatAttempt * mDelaySeconds, TimeUnit.SECONDS);
                        }
                    });
        }
    };
}

我想用flatmap包装错误,以便我可以检查异常类型,当它达到最大重试次数时,我可以将自定义异常传递给onError。

但是,当只使用Rxjava2时,timerWithRetries()方法停止工作,调用此方法但不执行.zipWith()及其flatmap。

但是它在包装错误时没有使用flatmap,这很奇怪。像

这样的东西
.retryWhen(error -> error.compose(timerWithRetries()))

非常赞赏任何建议!

2 个答案:

答案 0 :(得分:2)

1.x retryWhen使用保留在最后一个Throwable上的BehaviorSubject,并在有新订阅者时重播。这主要是由于它的“怪异”和#34;通过尝试支持大多数retryrepeat运营商来实施。

2.x使用PublishSubject并且通常只订阅一次(不再重新组合)。只有失败时的观察者才会收到错误值,但不会收到错误发射后的任何错误值。

实际上,observable.compose(timerWithRetries());并不完全正确,因为您不断向主题添加观察者而不清除之前的观察者。

最后一种情况是有效的,因为你使用count-flatMapped处理程序构建主要错误源,该处理程序作为对原始错误的响应而发出。

答案 1 :(得分:0)

我终于找到了解决方法。使用延迟()而不是使用zipWith()和flatmap()。

 AtomicInteger retryCounter = new AtomicInteger(0);

.retryWhen(error -> error.flatmap(e -> {
     if (e instanceof HttpException) {
         // code that deals with specific exception
        int retries = retryCounter.increaseAndGet();
        if (retries < MAX_RETRIES) {
            // Key point here, uses .delay()
            return Observable.just(new Object()).delay(delaySeconds, SECOND);
        }
     }
 }))