johnny_crq
johnny_crq

Reputation: 4391

rxjava android retryWhen not calling onError on last attempt

I have this code to attemp to connect to a xmpp server. Everything works fine except in the last attemp to try to connect, onError is not called on the subscriber and according to the doc, it should. What am i doing wrong?

@Override
public void connect(final AbstractXMPPConnection connection) {
    Observable.<AbstractXMPPConnection>create(subscriber -> {
        try {
            connection.connect();
        } catch (SmackException | IOException | XMPPException e) {
            e.printStackTrace();
            subscriber.onError(e);
        }
        })
         .retryWhen(attempts -> attempts.zipWith(Observable.range(1, 4), (n, i) -> i).flatMap(i -> {
             return Observable.timer(i, TimeUnit.SECONDS);
         }))
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<AbstractXMPPConnection>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                     if (callback != null)
                        callback.onFailedConnecting();
                }

                @Override
                public void onNext(AbstractXMPPConnection conn) {
                    if (callback != null)
                        callback.onConnected();
                }
            });
}

TLDR: on the last attempt, public void onError should be called and it is not

Upvotes: 1

Views: 1160

Answers (2)

Dimon
Dimon

Reputation: 71

I made this such way (Scala, RxScala):

.retryWhen(_
    .zipWith(Observable.just(1, 2, 3, -1))((t, i) => (t, i))
    .flatMap( tuple => tuple match {
      case (t, -1) => Observable.error(t)
      case (t, i) => Observable.timer(i seconds)
    }))

Maybe there is some kind of zipWith operator, which calls onError, with first non-pair element. It would be nice

Upvotes: 0

Diolor
Diolor

Reputation: 13450

You have:

.retryWhen(attempts -> attempts.zipWith(Observable.range(1, 4), (n, i) -> i).flatMap(i -> {        
   return Observable.timer(i, TimeUnit.SECONDS);
}))

this code will never emit an error so it will try exponentially (Timer) to retry but will never fail. Thus onError() will never be called.

If you want to catch the error either you need to pass it from the retryWhen with an explicit Observable.error() or delete the retryWhen part. :)

Upvotes: 1

Related Questions