Мое приложение должно сделать две вещи в целом:Предельные действия с оператором rxJava и retryWhen
- Принимать только один запрос к сети, в то же время
- Retry, если запрос не удалось
Вот как я его осуществить:
public class RequestsLocker {
private volatile boolean isLocked;
public <T> Observable.Transformer<T, T> applyLocker() {
if(!isLocked()) {
return observable -> observable
.doOnSubscribe(() -> {
lockChannel();
})
.doOnUnsubscribe(() -> {
freeChannel();
});
} else {
return observable -> Observable.error(new ChannelBusyException("Channel is busy now."));
}
}
private void lockChannel() {
isLocked = true;
}
private void freeChannel() {
isLocked = false;
}
public boolean isLocked() {
return isLocked;
}
}
Выглядит хорошо.
Теперь моя retryWhen
реализация:
public static Observable<?> retryWhenAnyIoExceptionWithDelay(Observable<? extends Throwable> observable) {
return observable.flatMap(error -> {
// For IOExceptions, we retry
if (error instanceof IOException) {
return Observable.timer(2, TimeUnit.SECONDS);
}
// For anything else, don't retry
return Observable.error(error);
});
}
Существует, как я использую его:
public Observable<List<QueueCarItem>> finishService(int id, PaymentType paymentType, String notes) {
return carsQueueApi.finishService(id, new FinishCarServiceRequest(paymentType.getName(), notes))
.compose(requestsLocker.applyLocker(RequestsLocker.RequestChannel.CHANGE));
}
...
public void finishCarService(QueueCarItem carItem, PaymentType paymentType,
String notes, Subscriber<List<QueueCarItem>> subscriber) {
queueApiMediator.finishService(carItem.getId(), paymentType, notes)
.subscribeOn(ioScheduler)
.observeOn(uiScheduler)
.doOnError(this::handleError)
.retryWhen(RxOperatorsHelpers::retryWhenAnyIoExceptionWithDelay)
.subscribe(subscriber);
}
Основная проблема, которая doOnUnsubscribe()
называется на любой ошибки и то шкафчик открыт для любого нового запроса до истечения таймера и повторной подписки снова. Это проблема. Пока таймер тикает, пользователь может сделать другой запрос.
Как я могу это исправить?
Не могли бы вы разместить код, показывающий, как вы на самом деле используете трансформатор applyLocker и 'retryWhenAnyIoExceptionWithDelay'? – JohnWowUs
@JohnWowUs готово. – Alexandr