RxJava2 - Как повторить попытку каждый раз, кроме случаев, когда это TimeoutException? - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть цепочка Observables, и в конце я пишу команду на устройство через Bluetooth и жду уведомления.Есть случай, когда он может ждать здесь вечно, поэтому я хотел бы использовать timeout - легко.

Но проблема в том, что я хочу retry каждый раз, когда возникает какая-либо другая проблема, она должна быть прервана только в случае timeout, в противном случае она должна retry.Кроме того, если мы пройдем по цепочке, мы встретим другие попытки, которые также должны иметь такое же поведение.Исключение тайм-аута должно быть перенесено обратно на верхний уровень (интерактив в моем случае).

Я думал о retryWhen, но я не уверен, как правильно использовать его в этом случае.

.retryWhen { it.filter { throwable -> throwable !is TimeoutException } }

Кроме того, для этого сложно написать тесты, поэтому мне труднее найти правильное решение.

1 Ответ

0 голосов
/ 01 февраля 2019

Пожалуйста, попробуйте следующий подход, который я использую для моего проекта.

Создайте класс (это Java-класс, вы можете изменить его на kotlin, если требуется)

public class RetryWithDelay implements Function<Observable<? extends Throwable>, Observable<?>> {
private static final String TAG = "RetryWithDelay";

private final int maxRetries;
private final int retryDelayInMinutes;
private int retryCount;



public RetryWithDelay(final int maxRetries, final int retryDelayInMinutes) {
    this.maxRetries = maxRetries;
    this.retryDelayInMinutes = retryDelayInMinutes;
    this.retryCount = 0;
}

@Override
public Observable<?> apply(Observable<? extends Throwable> attempts) {
    return attempts.flatMap(new Function<Throwable, Observable<?>>() {
        @Override
        public Observable<?> apply(Throwable throwable) {
            if (throwable instanceof TimeoutException) {
                return Observable.error(throwable);
            }

            if (++retryCount < maxRetries) {
                // When this Observable calls onNext, the original
                // Observable will be retried (i.e. re-subscribed).
                return Observable.timer(retryDelayInMinutes, TimeUnit.MINUTES);
            }

            // Max retries hit. Just pass the error along.
            return Observable.error(throwable);
        }
    });
}}

ВнутриПрименить метод, он проверит, является ли исключение экземпляром TimeOut, он выдаст ошибку, в противном случае он продолжит повторную попытку для желаемого maxRetries.

И передаст этот класс, как показано ниже

  .retryWhen (new RetyWithDelay(3,5)) 

Где он будет повторяться 3 раза каждые 5 минут.

...