davidmoten / davidmoten/rxjava2-extras

Feature request: allow RetryWhen to count only consecutive errors

Open
#16 2 comments 0 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.