You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The semantics would be "Retry when the count of consecutive errors has not exceeded a certain value." The error count would be reset upon a successful onNext call.
It could be done with a builder function like .consecutiveErrorCountLessThan( int n ). (If 2+ billion consecutive errors isn't enough, make the parameter a long :-)
I've implemented something like this as a composable ObservableTransformer. It also accepts an optional list of the types of Exception to be counted. Caveat: it's not well tested yet.
public class RetryLimiter<T> implements ObservableTransformer<T,T> {
private final static String TAG = RetryLimiter.class.getSimpleName();
private int errorCount = 0;
private int maxErrorCount;
private List<Class> countedExceptions; // note errors not in this list (if defined) are not counted and will continue retries
// constructor passes max tolerated consecutive errors (count is rezeroed upon a successful emission)
public RetryLimiter( int maxErrors ) {
if( maxErrors < 0 ) throw new IllegalArgumentException( "maxErrors cannot be < 0" );
maxErrorCount = maxErrors;
}
// constructor that accepts a list of the types of exceptions to count (others are ignored)
public RetryLimiter( int maxErrors, List<Class> exceptions ) {
this( maxErrors );
if( exceptions != null ) {
for( Class c : exceptions ) { // check that the supplied list contains only Throwable (sub)classes
if( !Throwable.class.isAssignableFrom( c ) ) { // is c a Throwable or subclass of Throwable?
throw new IllegalArgumentException( "List can only contain class Throwable or its subclasses" );
}
}
countedExceptions = exceptions;
} else {
throw new NullPointerException( "If supplied, Exception Class list cannot be null" );
}
}
@Override
public ObservableSource<T> apply( Observable<T> upstream ) {
return upstream
.doOnError( err -> {
if( countedExceptions != null ) {
for( Class t : countedExceptions ) {
if( err.getClass().equals( t ) ) {
errorCount++;
break; // don't count more than once
}
}
} else { // null list of counted Exceptions
errorCount++;
}
if( DEBUG ) Log.d( TAG, "Consecutive error #" + errorCount + ": " + err.toString() );
} )
.doOnNext( next -> errorCount = 0 )
.retryUntil( () -> errorCount > maxErrorCount );
}
}
Also, what about including an option for a general Predicate function to decide whether or not to retry? I realize this is essentially the same as the standard .retryUntil( Predicate ) but it could be a useful addition: .isTrue( Predicate p ). Not to gild the lily, but it could perhaps be two functions: .and( Predicate p ) and .or( Predicate p ). Arguments to the Predicate are TBD but would presumably include the Throwable.
The text was updated successfully, but these errors were encountered:
In your email you mentioned that your use case involves network IO. I suggest that a time-based retry is more appropriate. If you want to fail after 7 attempts with exponential backoff:
Is there any reason why time-based retries are not the go?
Note also that I would expect the retryWhen operator to be attached to each of the IO calls (the Singles you mentioned) rather than further downstream after the flatmap.
The semantics would be "Retry when the count of consecutive errors has not exceeded a certain value." The error count would be reset upon a successful
onNext
call.It could be done with a builder function like
.consecutiveErrorCountLessThan( int n )
. (If 2+ billion consecutive errors isn't enough, make the parameter along
:-)I've implemented something like this as a composable
ObservableTransformer
. It also accepts an optional list of the types ofException
to be counted. Caveat: it's not well tested yet.Also, what about including an option for a general
Predicate
function to decide whether or not to retry? I realize this is essentially the same as the standard.retryUntil( Predicate )
but it could be a useful addition:.isTrue( Predicate p )
. Not to gild the lily, but it could perhaps be two functions:.and( Predicate p )
and.or( Predicate p )
. Arguments to thePredicate
are TBD but would presumably include theThrowable
.The text was updated successfully, but these errors were encountered: