Reputation: 161
I've got a chain of Observables
and at the end of it, I'm writing a command to the device via Bluetooth and I'm waiting for the notification. There's a case, where it can wait here forever so I would like to use timeout
- easy.
But the problem is that, I want to retry
every time any other problem occurred, it should be terminated only if timeout
happen - otherwise it should retry
. Also, if we go down through the chain, we will meet other retries that also should have the same behavior. Timeout exception should be pushed back to the higher layer(interactor in my case).
I thought about retryWhen
but I'm not sure how to use it properly in that case.
.retryWhen { it.filter { throwable -> throwable !is TimeoutException } }
Also, it's hard to write tests for that so it makes it harder for me to find the right solution.
Upvotes: 1
Views: 1006
Reputation: 992
Please try this following approach which i am using for my project.
Create a class (It is a java class you can change it into kotlin if required)
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);
}
});
}}
Inside apply method, it will check if the exception is instance of TimeOut , it will throw an error else it will keep retrying for the maxRetries you want.
And pass this class as below
.retryWhen (new RetyWithDelay(3,5))
Where it will retry for 3 times every 5 mins.
Upvotes: 1