-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2.x: RxJavaPlugins unwrapRunnable #5734
Conversation
import io.reactivex.disposables.Disposable; | ||
import io.reactivex.exceptions.Exceptions; | ||
import io.reactivex.functions.Function; | ||
import io.reactivex.internal.disposables.*; | ||
import io.reactivex.internal.schedulers.*; | ||
import io.reactivex.internal.disposables.EmptyDisposable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure your IDE doesn't unroll star imports to reduce the diff size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
|
||
package io.reactivex.internal.schedulers; | ||
|
||
public interface SchedulerRunnableWrapper extends Runnable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document this interface a bit and include a @since 2.1.7 - experimental
tag and the @Experimental
class annotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
|
||
public interface SchedulerRunnableWrapper extends Runnable { | ||
|
||
Runnable getWrappedRunnable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a short description of this method and the @Nullable
annotation (some terminated wrappers do null out their wrapped Runnable
instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
* Unwraps internal scheduler's task. | ||
* @param task the internal task | ||
* @return the unwrapped runnable or task | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add @since 2.1.7 - experimental
and @Experimental
annotation to the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alos please add @Nullable
and @CheckReturnValue
to the return type, @NonNull
to the parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
import io.reactivex.Scheduler.Worker; | ||
import io.reactivex.disposables.*; | ||
import io.reactivex.disposables.Disposable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't unroll star imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Codecov Report
@@ Coverage Diff @@
## 2.x #5734 +/- ##
============================================
+ Coverage 96.28% 96.35% +0.07%
+ Complexity 5837 5833 -4
============================================
Files 634 634
Lines 41644 41650 +6
Branches 5768 5769 +1
============================================
+ Hits 40096 40131 +35
+ Misses 609 598 -11
+ Partials 939 921 -18
Continue to review full report at Codecov.
|
Please also make sure the |
Ok, I think that I've finished work with code coverage so if you will have time to review I'm open to continue discussion. |
@@ -368,7 +368,7 @@ public long now(@NonNull TimeUnit unit) { | |||
|
|||
@Override | |||
public void run() { | |||
decoratedRun.run(); | |||
getWrappedRunnable().run(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't turn these into method calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you give me small tip? Without invoking getWrappedRunnable I don't have a 100% code coverage in Scheduler.java because I'm using the method only in RxJavaPlugins which has 100% code coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this type of task is created and returned, then invoke unwrapRunnable
on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean something like that?
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
DisposeTask task = new DisposeTask(decoratedRun, w);
w.schedule(task, delay, unit);
return RxJavaPlugins.unwrapRunnable(task);
}
but in that case I have incompatible types Disposable and Runnable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, do the unwrapping in the unit test. Also for convenience, the unwrapRunnable should perhaps accept Object
instead of Runnable
.
@@ -1,48 +1,48 @@ | |||
/** | |||
* Copyright (c) 2016-present, RxJava Contributors. | |||
* | |||
* <p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please restore the header to the standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't have yours code style and I have still the same problem with formating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I corrected it.
|
||
public class SchedulerTest { | ||
|
||
@Test | ||
public void defaultPeriodicTask() { | ||
final int[] count = { 0 }; | ||
final int[] count = {0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't change unrelated tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course I will change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I corrected it.
* @since 2.1.7 - experimental | ||
*/ | ||
@Experimental | ||
public interface SchedulerRunnableWrapper extends Runnable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not certain this should extend Runnable
as it may make developers think they should invoke run
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chaged it.
import io.reactivex.*; | ||
import io.reactivex.Scheduler.Worker; | ||
import io.reactivex.annotations.NonNull; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please completely restore this file before this PR so it doesn't show up as diff at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope I've finally had the order. :)
I think is ok now. I hope so :) |
Thank you very much for support. :) |
Sorry I didn't get in earlier, This API seems to be inconsistent with other introspection APIs like While this PR adds very generic method to Shouldn't we make interface public and document how to use it in the Additional thought, probably no one would need it outside of |
Hi, Do you suggest that adding better description how to use Of course I'm open to discussion :) |
@akarnokd @artem-zinnatullin I made changes based on your tips. |
@@ -0,0 +1,35 @@ | |||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this into io.reactivex.schedulers
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -43,11 +32,22 @@ | |||
import io.reactivex.internal.operators.observable.ObservableRange; | |||
import io.reactivex.internal.operators.parallel.ParallelFromPublisher; | |||
import io.reactivex.internal.operators.single.SingleJust; | |||
import io.reactivex.internal.schedulers.ImmediateThinScheduler; | |||
import io.reactivex.internal.schedulers.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that this doesn't have an extra method, please restore the pre-PR version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -48,6 +37,17 @@ | |||
import io.reactivex.observables.ConnectableObservable; | |||
import io.reactivex.parallel.ParallelFlowable; | |||
import io.reactivex.schedulers.Schedulers; | |||
import org.junit.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still shows up as changed because the imports. Please use the version from HEAD to restore this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ehh it is the same mistake :)
I've fixed it.
import io.reactivex.plugins.RxJavaPlugins; | ||
|
||
/** | ||
* Marker interface to indicate wrapped action inside internal scheduler's task. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a marker interface if it declares method(s) that can be consumed :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True :)
* Inside of the {@link RxJavaPlugins#onSchedule(Runnable)}, you can unwrap runnable from internal wrappers like | ||
* {@link Scheduler.DisposeTask}. | ||
* | ||
* @since 2.1.7 - experimental |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add "see also" with references to RxJavaPlugins.setScheduleHandler()
and RxJavaPlugins. getScheduleHandler()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about something like this?
/**
* Interface to wrap an action inside internal scheduler's task.
*
* You can check if runnable implements this interface and unwrap original runnable.
* For example inside of the {@link RxJavaPlugins#setScheduleHandler(Function)}
*
* @since 2.1.7 - experimental
*/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I corrected it.
/** | ||
* Marker interface to indicate wrapped action inside internal scheduler's task. | ||
* | ||
* Inside of the {@link RxJavaPlugins#onSchedule(Runnable)}, you can unwrap runnable from internal wrappers like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe change to something like:
You can check if runnable implements this interface and unwrap original runnable?
}; | ||
SchedulerRunnableIntrospection wrapper = (SchedulerRunnableIntrospection) scheduler.schedulePeriodicallyDirect(runnable, 100, 100, TimeUnit.MILLISECONDS); | ||
|
||
assertEquals(runnable, wrapper.getWrappedRunnable()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertSame?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls fix comments, otherwise LGTM :)
* Inside of the {@link RxJavaPlugins#onSchedule(Runnable)}, you can unwrap runnable from internal wrappers like | ||
* {@link Scheduler.DisposeTask}. | ||
* | ||
* @since 2.1.7 - experimental |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sgtm
* | ||
* @return the wrapped action, may be null. | ||
*/ | ||
@Nullable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually is @NotNull
now since it's not a generic Object based API, schedulers don't expect that Runnable
can be null (I'm adding PR that'll enforce that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I corrected it
@@ -307,4 +307,66 @@ public void customScheduleDirectDisposed() { | |||
|
|||
assertTrue(d.isDisposed()); | |||
} | |||
|
|||
@Test | |||
public void unwrapDefaultPeriodicTask() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we move these tests to AbstractSchedulerTests
@akarnokd?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm waiting for your decision :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're waiting for @akarnokd to answer I'd recommend you to try to move this code to AbstractSchedulerTests
and make sure to use getScheduler()
instead of TestScheduler
, that way we check that all schedulers properly support this introspection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to check that all schedulers support this API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can get complicated and this is an optional introspection. If @lukaszguz wants to expand it, then sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, but I'd encourage @lukaszguz to try that and ask for help if needed, would be great to provide as robust API experience as possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's enough for now? I can always add a new PR with additional tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with this as is. We can always expand the feature set later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my first time when I'm doing PR to your library. Thanks to your tips, I know more or less what your requirements are and I can write better code. I think the better option would be to leave those tests in SchedulerTest
because they are showed how Scheduler
works but also good idea is to add tests in AbstractSchedulerTests
which they will guarantee compatibility with all rx's schedulers
Alright, I'm not blocking this PR, just realistically these tests won't be
written in future until someone face a bug (which I've now affected as an
observer by making this comment lol)
…On Thu, Nov 30, 2017, 11:54 AM lukaszguz ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/test/java/io/reactivex/schedulers/SchedulerTest.java
<#5734 (comment)>:
> @@ -307,4 +307,66 @@ public void customScheduleDirectDisposed() {
assertTrue(d.isDisposed());
}
+
+ @test
+ public void unwrapDefaultPeriodicTask() {
This is my first time when I'm doing PR to your library. Thanks to your
tips, I know more or less what your requirements are and I can write better
code. I think the better option would be to leave those tests in
SchedulerTest because they are showed how Scheduler works but also good
idea is to add tests in AbstractSchedulerTests which they will guarantee
compatibility with all rx's schedulers
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5734 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA7B3Dy4ARqSIUhspyjU3T8eMceIEvBCks5s7wgHgaJpZM4Qlqsh>
.
|
I wrote tests to |
|
||
@Override | ||
public Runnable getWrappedRunnable() { | ||
return get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dispose()
will swap in a null but the method is defined as @NotNull
. So either the interface should allow nulls or this should return Functions.EMPTY_RUNNABLE:
Runnable r = get();
return r != null ? r : Functions.EMPTY_RUNNABLE;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ehhh I did not notice it. I will check what will happen when dispose return Functions.EMPTY_RUNNABLE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All tests were passed with this change. I will leave with:
Runnable r = get();
return r != null ? r : Functions.EMPTY_RUNNABLE;
@Override | ||
public Runnable getWrappedRunnable() { | ||
Runnable r = get(); | ||
return r != null ? r : Functions.EMPTY_RUNNABLE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative solution could be to throw IllegalStateException
I guess
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a failure state but a terminal state of the wrapper. Penalizing it would be too harsh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this particular introspection api it seems like an invalid state, but I'm ~fine with current solution.
The problem of returning empty runnable is that since it's the same object every time — it can mess up introspection that is based on object identity/equality
Thanks for addressing feedback! |
Hi,
RxJava2 version: [2.1.6]
It is reference to #5733