Meine Anwendung muss in der Regel zwei Dinge tun:Limit-Aktionen mit rxJava und retryWhen Betreiber
- nur eine Netzwerkanfrage zur gleichen Zeit Accept
- Retry wenn Anfrage
fehlgeschlagen Das ist, wie ich Implementieren Sie es:
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;
}
}
Sieht gut aus.
Nun meine retryWhen
Umsetzung:
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);
});
}
Es ist, wie ich es verwenden:
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);
}
Das Hauptproblem, dass doOnUnsubscribe()
bei jedem Fehler genannt und Dann ist das Schließfach für jede neue Anfrage offen, bis der Timer abläuft und neu happiert ens wieder. Das ist das Problem. Während der Timer tickt, kann der Benutzer eine andere Anfrage stellen.
Wie kann ich es beheben?
Könnten Sie einen Code veröffentlichen, der zeigt, wie Sie 'applyLocker' transformator und' retryWhenAnyIoExceptionWithDelay' tatsächlich verwenden? – JohnWowUs
@ JohnWowUs bereit. – Alexandr