davidmoten / davidmoten/rxjava2-extras
Feature request: allow RetryWhen to count only consecutive errors
- Dominant language
- Java
- Stars
- 172
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
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 implements ObservableTransformer {
private final static String TAG = RetryLimiter.class.getSimpleName();
private int errorCount = 0;
private int maxErrorCount;
private List 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 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 apply( Observable 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`.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.