These are chat archives for ReactiveX/RxJava

16th
Nov 2015
Javier Domingo Cansino
@txomon
Nov 16 2015 00:13
Ok, I am back with another problem, I don't understand how to use retryWhen
xD
that documentation is overly complex without simple explanations
and on top of that, we have the super easy to read Java syntax :(
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:17
@txomon imagine you're doing Network request via Observable and you want to retry it if some exception was thrown then you can use retry or retryWhen to do it!
Of course, Observable must be "cold" (do work from scratch each time new subscriber subscribes)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:19
@artem-zinnatullin the problem is trying to understand what it needs
I mean, retry needs a boolean that says continue/stop
but retryWhen seems like it needs an observable that will trigger something after a delay
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:26
@txomon it takes an Observable that controls when retryWhen should do its work
Javier Domingo Cansino
@txomon
Nov 16 2015 00:27
but the thing is, I should have a way to receive that exception
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:27
Each emission of the Observable returned by your function in retryWhen makes retry attempt
Javier Domingo Cansino
@txomon
Nov 16 2015 00:27
but I see none
I mean, within my function I want to retry if the exception is a custom one
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:28
Okay :) You got Observable<? extends Throwable> for it
Let's see on the example
Javier Domingo Cansino
@txomon
Nov 16 2015 00:28
                public Observable<?> call(Observable<? extends Throwable> observable) {
                    if (observable instanceof UbusRpcException)
                        return Observable.timer(5, TimeUnit.SECONDS);
                    return null;
                }
that one
but the problem is that instanceof won't work there
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:29
Sure, Observable can not be UbusRpcException :)
you have to take this exception from the observable
for example, observable.toBlocking.first()
or you can use flatMap
Also, I guess, you can not return null, return Observable.empty() instead
Javier Domingo Cansino
@txomon
Nov 16 2015 00:30
    Observable
            .just(true)
            .observeOn(Schedulers.io())
            .flatMap(new Func1<Boolean, Observable<Boolean>>() {
                @Override
                public Observable<Boolean> call(Boolean aBoolean) {
                    try {
                        return Observable.just(currentClient.update());
                    } catch (UbusRpcException e) {
                        return Observable.error(e);
                    }
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .doOnError(new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    if (throwable instanceof UbusRpcException) {
                        handleCallError(throwable.getMessage());
                    }
                }
            })
            .retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
                @Override
                public Observable<?> call(Observable<? extends Throwable> observable) {
                    if (observable instanceof UbusRpcException)
                        return Observable.timer(5, TimeUnit.SECONDS);
                    return Observable.empty();
                }
            })
            .retry(new Func2<Integer, Throwable, Boolean>() {
                @Override
                public Boolean call(Integer integer, Throwable throwable) {
                    return throwable instanceof UbusRpcException;
                }
            });
ok that is my code
the .retryWhen() is supposed to replace the retry()
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:33
I'd write this:
retryWhen(observableWithError -> {
  if (observableWithError.toBlocking().first() instanceof UbusRpcException) {
    return Observable.timer(5, SECONDS);
  }
  return Observable.empty();
})
As said before, you can not cast Observable to exception :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:33
oh so that is extracting the error from the observable?
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:34
yep
Javier Domingo Cansino
@txomon
Nov 16 2015 00:34
and why the toBlocking()?
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:34
Because your code waits for the value and should block until it resolved
Give me 20 seconds and I'll post another solution with flatMap :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:35
nono
I like this one
is there any way to schedule an action?
because I find no way to execute my function without that just(true)
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:36
retryWhen(observableWithError -> observableWithError.flatMap(exception -> instanceof UbusRpcException ? Observable.timer(5, SECONDS) : Observable.empty())
Sorry, I couldn't stop myself :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:36
haha no problem
Dorus
@Dorus
Nov 16 2015 00:36
@txomon Why are you using retryWhen? I told you to use Retry. Also your observable (the clicks) are hot, but this is not a problem. All you want to archive withRetry is listen to the next click, the current click already failed.
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:36

is there any way to schedule an action?

What do you mean?

Javier Domingo Cansino
@txomon
Nov 16 2015 00:37
@Dorus this is another. This a network operation that I want to be retried
until it succeeds
@artem-zinnatullin I am trying to call a function in another thread that will do heavy network work
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:38
Okay, I see what did you mean. Well, I'd say that you need to learn Rx basics. Please don't take it as aggression :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:38
so I created that Observable as a way to call the function in another thread
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:38
Yeah I see
There is subscribeOn for such things, of course it's doable in your way, but it's more trick than a good solution
Javier Domingo Cansino
@txomon
Nov 16 2015 00:39
I am already using that
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:39
I understand
Javier Domingo Cansino
@txomon
Nov 16 2015 00:39
oh no, is observeOn
Dorus
@Dorus
Nov 16 2015 00:39
I taught you well
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:39
observeOn changes the thread of emission, not the beginning of the subscription
Javier Domingo Cansino
@txomon
Nov 16 2015 00:39
anyway, the thing is that I don't understand how to make it without the flatMap
and without the .just(true)
I would prefer that the .just(true) was an empty or something, but then I run into errors with the .flatMap() obviously (there is nothing to map)
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:41
@txomon just(true).observeOn() is a trick, better solution is to write yourObservable.subscribeOn()
Javier Domingo Cansino
@txomon
Nov 16 2015 00:42
@artem-zinnatullin you don't agree with @Dorus then
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:42
@txomon do you have 30-60 minutes to watch some videos about Rx (RxJava)? I think you'll understand what I mean :)
Dorus
@Dorus
Nov 16 2015 00:42
nah in this case subscribeOn is correct actually
Javier Domingo Cansino
@txomon
Nov 16 2015 00:43
haha ok
Dorus
@Dorus
Nov 16 2015 00:43
Because you do the function call in the source of the observable
Javier Domingo Cansino
@txomon
Nov 16 2015 00:43
I just realized that empty() -> is a notification
Dorus
@Dorus
Nov 16 2015 00:43
and subscribe on controlls the t hread that create the source.
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:43
@txomon I think it'll save you a lot time in future!
Javier Domingo Cansino
@txomon
Nov 16 2015 00:43
so I can doOnEach()
@artem-zinnatullin links?
@Dorus but as always, I need to do the stuff in another thread, not the one that creates this
Dorus
@Dorus
Nov 16 2015 00:44
Anyway in this case i would first schedule the function on a off thread, and then convert it to an observable.
Althou i'm not sure how easy that is in java :D
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:45

@txomon I'd sent you a link to my talk about Rx where I describe this things from practice point, but video in Russian :(

Can not recommend any particular video in English, unfortunately, I've watched about 10 of them and compiled material in my head.

Javier Domingo Cansino
@txomon
Nov 16 2015 00:46
yeah, and without the lambdas it's still more difficult
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:46
@Dorus there are tons of ways to do that in RxJava
Javier Domingo Cansino
@txomon
Nov 16 2015 00:46
uff russian not in my set of languages
Dorus
@Dorus
Nov 16 2015 00:46
yeah, it's easy in C# where i come from, i'm sure java can do it too.
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:46
Observable.fromCallable(() -> { your_code }).subscribeOn()
Dorus
@Dorus
Nov 16 2015 00:47
yes that! Looks good.
Javier Domingo Cansino
@txomon
Nov 16 2015 00:47
yeah, I suppose I didn't do the callable thing because I don't know that much Java still xD
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:47
Observable.defer(() -> { Observable.just(your_code)).subscribeOn()
@txomon it's just a function returning some value
Javier Domingo Cansino
@txomon
Nov 16 2015 00:48
gosh I hate the non lambda thing
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:48
Observable.create(subscriber -> {
  subscriber.onNext(your_code);
  subscriber.onCompleted();
}).subscribeOn()
@txomon then use lamdas!
Javier Domingo Cansino
@txomon
Nov 16 2015 00:48
yeah I was doing that before
I am on android
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:49
There is Retrolambda
Javier Domingo Cansino
@txomon
Nov 16 2015 00:49
and I don't know how to use retrolambda
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:49
// I'm an Android developer too, btw
Javier Domingo Cansino
@txomon
Nov 16 2015 00:49
hahaha
I am embedded developer, C/Python and electronics
UIs are so out of scope of what I do...
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:49
Setup is pretty easy, check https://github.com/evant/gradle-retrolambda
Another solution — use some JVM language with Lambdas: Kotlin, Groovy, Scala, etc
Javier Domingo Cansino
@txomon
Nov 16 2015 00:50
not an option, I need to learn little by little
I am learning too many things at the same time already
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:51
Never stop :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:51
yeah, not stopping but heh
Dorus
@Dorus
Nov 16 2015 00:52
Another question, why do you use both RetryWhen and Retry?
Javier Domingo Cansino
@txomon
Nov 16 2015 00:52
oh that was just to ease development
and see I wasn't forgetting something
the .retry() was going to be erased
Dorus
@Dorus
Nov 16 2015 00:53
good :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:53
    Observable
            .fromCallable(
                    new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            return currentClient.update();
                        }
                    }
            )
            .retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
                @Override
                public Observable<?> call(Observable<? extends Throwable> observable) {
                    if (observable.toBlocking().first() instanceof UbusRpcException)
                        return Observable.timer(5, TimeUnit.SECONDS);
                    return Observable.empty();
                }
            })
            .subscribe();
this is the final form
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:53
And you forgot subscribeOn() before subscribe() :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:53
oh hell
yeah
hahah
Dorus
@Dorus
Nov 16 2015 00:54

Another valid use of subscribeOn is to keep ownership of the subscribing thread, typical when the subscribe action is long-running. I dont think that's the case when your source is Events.click.

This is that another valid use. You are creating a observalbe that runs a long running action that you obviouse do not want to run on the current (main) thread.

Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:54
LGTM, but lambdas
@Dorus …? :)
Dorus
@Dorus
Nov 16 2015 00:55
Oh i'm repeating what i told txomon yesterday
Why i tought it was bad to use subscribeOn yesterday.
this is one of the cases where it isn't bad.
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:56
Voices in your head told you do that!
Javier Domingo Cansino
@txomon
Nov 16 2015 00:56
hahaha
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:57
Okay, I should go sleep now :)
Javier Domingo Cansino
@txomon
Nov 16 2015 00:57
@artem-zinnatullin do you add gradle/ ?
not related to this, but to git
I don't know if gitignore it or not
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:57
@txomon you mean do I use gradle or what?
Javier Domingo Cansino
@txomon
Nov 16 2015 00:57
no no
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:57
oh, you mean Gradle wrapper?
Javier Domingo Cansino
@txomon
Nov 16 2015 00:57
gitignore /gradle/
on the source tree
I wanted to upload latest code
no worries, I will find out myself
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 00:59
okay, simple explanation:
  • Gradle is build system
  • Gradle has ultra-duper-awesome feature: Gradle Wrapper — it's lightweight .jar that can work as Gradle (if Gradle is not installed, it'll download it)
And yes, you should commit gradlew (Gradle wrapper) to the source control system
Javier Domingo Cansino
@txomon
Nov 16 2015 00:59
I was asking about /gradle/
the folder
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:00
Yep, ignore .gradle folder and /build
Javier Domingo Cansino
@txomon
Nov 16 2015 01:00
no, /gradle/ folder
not /.gradle/
xD
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:00
oh Jesus, so many folders
Javier Domingo Cansino
@txomon
Nov 16 2015 01:00
gradle
gradle/wrapper
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
yeah hahah
I will ignore it for the moment, no worries
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:01
gradle should BE committed
no no, do not ignore it
Javier Domingo Cansino
@txomon
Nov 16 2015 01:01
oh ok
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:01
it's folder for Gradle wrapper
Javier Domingo Cansino
@txomon
Nov 16 2015 01:01
oki then haha
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:01
As said before — it's needed to be committed (in most of the cases)
@txomon can I go sleep then? :)
Javier Domingo Cansino
@txomon
Nov 16 2015 01:02
thank you both!! have a good night!
yeah
hahaha
I am going too
Artem Zinnatullin :slowpoke:
@artem-zinnatullin
Nov 16 2015 01:02
phew :) Thanks
Dorus
@Dorus
Nov 16 2015 01:05
Good night too
txomon @txomon will continue a little bit more...
Dorus
@Dorus
Nov 16 2015 01:06
Just ask if you have more questions. I'm sure somebody here will pick up on them, or we will tomorrow ;)
At least, dont bother us with compile errors :P
Javier Domingo Cansino
@txomon
Nov 16 2015 01:09
yeah haha no worries
I now monitor my /tmp space