Skip to content

2.x: option to fail for using blockingX on the computation scheduler#5020

Merged
akarnokd merged 3 commits intoReactiveX:2.xfrom
akarnokd:BlockingOnComputation
Jan 27, 2017
Merged

2.x: option to fail for using blockingX on the computation scheduler#5020
akarnokd merged 3 commits intoReactiveX:2.xfrom
akarnokd:BlockingOnComputation

Conversation

@akarnokd
Copy link
Member

@akarnokd akarnokd commented Jan 25, 2017

This PR adds an RxJavaPlugins option failOnNonBlockingScheduler that triggers an IllegalStateException when the user tries to run a blocking method while the execution is on the computation() or single() Scheduler:

Flowable.just(1)
.subscribeOn(Schedulers.computation())
.map(v -> Flowable.just("query").subscribeOn(Schedulers.io()).blockingFirst())
.doOnNext(v -> someAPI(v).subscribeOn(Schedulers.newThread()).blockingSubscribe());
.blockingFirst();

It is an optional setting, default off.

The check is done before going into an await method (and a few other types of blocking). Most blocking operators usually poll the status and try to avoid the actual blocking thus this shouldn't affect synchronous sequences that one extracts a value from.

Detection of a blocking-sensitive scheduler's thread is done by checking the current thread's class for implementing the NonBlockingThread marker interface (currently internal).

The RxThreadFactory has been updated to allow picking a default Thread implementation or a custom one for the newThread(). Note that since #5002 you can create custom schedulers by providing a ThreadFactory.

This works for RxJava's default schedulers but not for AndroidSchedulers.mainThread() where similar blocking should be avoided as well. For them, a plugin-callback action would be more suitable. Question is how that callback should behave (throw, return false, should it be always executed or only when the flag is true).

My proposed solution is to have a plugin callback RxJavaPlugins.setOnBeforeBlocking(BooleanSupplier) that Android users can define the callback for:

RxJavaPlugins.setOnBeforeBlocking(() -> Looper.myLooper() == Looper.getMainLooper())
RxJavaPlugins.setFailOnNonBlockingScheduler(true);

This callback is only executed if the failOnNonBlockingScheduler is set to true.

@akarnokd akarnokd added this to the 2.1 milestone Jan 25, 2017
@akarnokd akarnokd requested a review from JakeWharton January 26, 2017 08:23
@codecov-io
Copy link

Current coverage is 95.67% (diff: 92.45%)

Merging #5020 into 2.x will increase coverage by 0.14%

@@                2.x      #5020   diff @@
==========================================
  Files           609        609          
  Lines         39379      39427    +48   
  Methods           0          0          
  Messages          0          0          
  Branches       6025       6030     +5   
==========================================
+ Hits          37616      37720   +104   
+ Misses          764        734    -30   
+ Partials        999        973    -26   

Powered by Codecov. Last update f53e029...ac942d2

* @since 2.0.5 - experimental
*/
@Experimental
public static void setOnBeforeBlocking(BooleanSupplier handler) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a use case in mind for exposing this API in addition to just the boolean?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the updated PR description.

@akarnokd akarnokd merged commit 307f97b into ReactiveX:2.x Jan 27, 2017
@akarnokd akarnokd deleted the BlockingOnComputation branch January 27, 2017 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants