Releases: ReactiveX/RxJava
1.0.13
This release has quite a few bug fixes and some new functionality. Items of note are detailed here with the list of changes at the bottom.
merge
The merge
operator went through a major rewrite to fix some edge case bugs in the previous version. This has been sitting for months going through review and performance testing due to the importance and ubiquity of its usage. It is believed this rewrite is now production ready and achieves the goal of being more correct (no known edge cases at this time) while retaining comparable performance and memory usage.
Special thanks to @akarnokd for this as merge
is a challenging one to implement.
window fix and behavior change
Unsubscription bugs were fixed in window
. Along the way it also resulted in a fix to one of the window
overloads that had a functional discrepancy.
window(Func0<? extends Observable<? extends TClosing>> closingSelector)
This is a small behavior change that corrects it. If you use this overload, please review the change to ensure your application is not affected by an assumption of the previously buggy behavior: #3039
Note that this behavior change only affects that particular overload while the broader bug fixes affect all window
overloads.
rx.Single
After much discussion it was decided to add a new type to represent an Observable
that emits a single item. Much bike-shedding led to the name Single
. This was chosen because Future
, Promise
and Task
are overused and already have nuanced connotations that differ from rx.Single
, and we didn't want long, obnoxious names with Observable
as a prefix or suffix. Read the issue thread if you want to dig into the long debates.
If you want to understand the reasoning behind adding this type, you can read about it in this comment.
In short, request/response semantics are so common that it was decided worth creating a type that composes well with an Observable
but only exposes request/response. The difference in behavior and comparability was also deemed worth having an alternative to Future
. In particular, a Single
is lazy whereas Future
is eager. Additionally, merging of Single
s becomes an Observable
, whereas combining Future
s always emits another Future
.
Note that the API is added in an @Experimental
state. We are fairly confident this will stick around, but are holding final judgement until it is used more broadly. We will promote to a stable API in v1.1 or v1.2.
Examples below demonstrate use of Single
.
// Hello World
Single<String> hello = Single.just("Hello World!");
hello.subscribe(System.out::println);
// Async request/response
Single<String> one = getData(1);
Single<String> two = getOtherData(2);
// merge request/responses into an Observable of multiple values (not possible with Futures)
Observable<String> merged = one.mergeWith(two);
// zip request/responses into another Single (similar to combining 2 Futures)
Single<String> zipped = one.zipWith(two, (a, b) -> a + b);
// flatMap to a Single
Single<String> flatMapSingle = one.flatMap(v -> {
return getOtherData(5);
});
// flatMap to an Observable
Observable<Integer> flatMapObservable = one.flatMapObservable(v -> {
return Observable.just(1, 2, 3);
});
// toObservable
Observable<String> toObservable = one.toObservable();
// toSingle
Single<Integer> toSingle = Observable.just(1).toSingle();
public static Single<String> getData(int id) {
return Single.<String> create(s -> {
// do blocking IO
s.onSuccess("data_" + id);
}).subscribeOn(Schedulers.io());
}
public static Single<String> getOtherData(int id) {
return Single.<String> create(s -> {
// simulate non-blocking IO
new Thread(() -> {
try {
s.onSuccess("other_" + id);
} catch (Exception e) {
s.onError(e);
}
}).start();
});
}
ConnectableObservable.autoConnect
A new feature was added to ConnectableObservable
similar in behavior to refCount()
, except that it doesn't disconnect when subscribers are lost. This is useful in triggering an "auto connect" once a certain number of subscribers have subscribed.
The JavaDocs and unit tests are good places to understand the feature.
Deprecated onBackpressureBlock
The onBackpressureBlock
operator has been deprecated. It will not ever be removed during the 1.x lifecycle, but it is recommended to not use it. It has proven to be a common source of deadlocks and is difficult to debug. It is instead recommended to use non-blocking approaches to backpressure, rather than callstack blocking. Approaches to backpressure and flow control are discussed on the wiki.
Changes
- Pull 3012 rx.Single
- Pull 2983 Fixed multiple calls to onStart.
- Pull 2970 Deprecated onBackpressureBlock
- Pull 2997 Fix retry() race conditions
- Pull 3028 Delay: error cut ahead was not properly serialized
- Pull 3042 add backpressure support for defaultIfEmpty()
- Pull 3049 single: add toSingle method to Observable
- Pull 3055 toSingle() should use unsafeSubscribe
- Pull 3023 ConnectableObservable autoConnect operator
- Pull 2928 Merge and MergeMaxConcurrent unified and rewritten
- Pull 3039 Window with Observable: fixed unsubscription and behavior
- Pull 3045 ElementAt request management enhanced
- Pull 3048 CompositeException extra NPE protection
- Pull 3052 Reduce test failure likelihood of testMultiThreadedWithNPEinMiddle
- Pull 3031 Fix OperatorFlatMapPerf.flatMapIntPassthruAsync Perf Test
- Pull 2975 Deprecate and rename two timer overloads to interval
- Pull 2982 TestSubscriber - add factory methods
- Pull 2995 switchOnNext - ensure initial requests additive and fix request overflow
- Pull 2972 Fixed window(time) to work properly with unsubscription, added
- Pull 2990 Improve Subscriber readability
- Pull 3018 TestSubscriber - fix awaitTerminalEventAndUnsubscribeOnTimeout
- Pull 3034 Instantiate EMPTY lazily
- Pull 3033 takeLast() javadoc fixes, standardize parameter names (count instead of num)
- Pull 3043 TestSubscriber javadoc cleanup
- Pull 3065 add Subscribers.wrap
- Pull 3091 Fix autoConnect calling onStart twice.
- Pull 3092 Single.toObservable
Artifacts: Maven Central
1.0.12
- Pull 2963 Set of standard producers and updated queue implementations
- Pull 2961 fix Amb backpressure bug
- Pull 2960 fix OperatorConcat race condition where request lost
- Pull 2985 improve OperatorSerializeTest.testMultiThreadedWithNPEinMiddle
- Pull 2986 OperatorAll - implement backpressure & include last value in exception cause
- Pull 2987 fix skip() race condition and request overflow
- Pull 2988 Operator exists() - implement backpressure & include last value in exception cause
- Pull 2989 prevent take() from requesting more than needed
- Pull 2991 takeUntil(predicate) - include last value in error cause
- Pull 2992 Fix value rendering in error last cause for primitive types
- Pull 2993 takeWhile(predicate) - include last value in error cause
- Pull 2996 switchIfEmpty - fix backpressure bug and lost requests
- Pull 2999 Fix a wrong assertion in assertError
- Pull 3000 Replace the Java 7 AssertionError(message, cause) with initCause
- Pull 3001 use Subscribers.from()
- Pull 3009 Observable.from(iterable) - ensure it.hasNext() is not called unnecessarily
Artifacts: Maven Central
1.0.11
- Pull 2948 More assertions for TestSubscriber
- Pull 2956 OperatorObserveOn should not request more after child is unsubscribed
- Pull 2951 OperatorConcat - prevent request overflow and fix race condition
- Pull 2950 OperatorGroupBy - check for request overflow and don't decrement when at Long.MAX_VALUE
- Pull 2923 OnBackpressureLatest: Non-blocking version of the toBlocking().latest() operator.
- Pull 2907 Fixed schedule race and task retention with ExecutorScheduler.
- Pull 2929 OperatorObserveOn onComplete can be emitted despite onError being called
- Pull 2940 Remove unnecessary localHasValue check
- Pull 2939 publish: Fix another race between terminalEvent and the queue being empty.
- Pull 2938 Fixed Observable.combineLatest overflow bug on Android
- Pull 2936 Fix TestSubject bug
- Pull 2934 Fix termination race condition in OperatorPublish.dispatch
- Pull 2963 Set of standard producers and updated queue implementations with some
Artifacts: Maven Central
1.0.10
- Pull 2892 Fix Observable.range race condition
- Pull 2895 Fix Observable.from(Iterable) race condition
- Pull 2898 Observable.range - add unit test for eager completion on empty
- Pull 2899 Observable.from(empty) to emit onComplete even when 0 requested
- Pull 2894 Concat: fixed reentrancy problem in completeInner
- Pull 2880 Use singleton reduction functions in count and countLong
- Pull 2902 Prevent ExceptionsTest from hanging when testing stack overflow
- Pull 2897 Fix for overlapping windows.
- Pull 2904 TakeLast - add request overflow check
- Pull 2905 Use singleton Operators where we can
- Pull 2909 Fix the drainer to check if the queue is empty before quitting.
- Pull 2911 OperatorPublish benchmark
- Pull 2914 Optimization - use OperatorTakeLastOne for takeLast(1)
- Pull 2915 Observable.ignoreElements - optimize
- Pull 2883 Proposal: standardized Subject state-peeking methods.
- Pull 2901 Operators toList and toSortedList now support backpressure
- Pull 2921 OperatorObserveOn - handle request overflow correctly
- Pull 2882 OperatorScan - don't call onNext after onError is called
- Pull 2875 Fix: NPE in requestFromChild method.
- Pull 2814 Operator Publish full rewrite
- Pull 2820 Backpressure for window(size)
- Pull 2912 Fix the Scheduler performance degradation
Artifacts: Maven Central
1.0.9
- Pull 2845 Fix for repeat: wrong target of request
- Pull 2851 Add 'request(Long.MAX_VALUE)' in 'onStart' to fix the backpressure issue of debounce
- Pull 2852 Change retryWhen to eagerly ignore an error'd source's subsequent events
- Pull 2859 OperatorDoOnRequest should unsubscribe from upstream
- Pull 2854 Fixes wrong request accounting in AbstractOnSubscribe
- Pull 2860 OperatorSingle should request exactly what it needs
- Pull 2817 Fix for non-deterministic: testOnBackpressureDropWithAction
- Pull 2818 Small fix for the getValue javadoc in AsyncSubject and BehaviorSubject
- Pull 2823 Enable maven central sync via bintray
- Pull 2807 Corrected all Java interfaces declarations
- Pull 2632 Implement hook to render specific types in OnNextValue
- Pull 2837 Fixed a non-deterministic test and a few scheduler leaks (in tests)
- Pull 2825 Fixed javadoc for Observable.repeat() method
- Pull 2838 Fix typo in OnSubscribe interface's Javadoc
- Pull 2864 IndexedRingBuffer.getInstance can infer type
- Pull 2862 Cleanup warnings in test source
- Pull 2868 Fixed reentrancy issue with the error producer.
- Pull 2866 Use simpler naming in Action1, Func1 to assist IDEs
Artifacts: Maven Central
1.0.8
- Pull 2809 Fixed takeUntil not unsubscribing from either of the observables in case of a terminal condition.
- Pull 2804 ObserveOn throughput enhancements
- Pull 2767 Optimized scalar observeOn/subscribeOn
- Pull 2776 Experimental: add new operator onBackpressureDrop(Action1 onDrop)
- Pull 2788 Fix the bug that 'publish' will cache items when no subscriber
- Pull 2779 OperatorMulticast.connect(connection) should not return null
- Pull 2771 OnSubscribeRange request overflow check
- Pull 2770 OperatorOnBackpressureDrop request overflow check
- Pull 2769 OperatorCombineLatest request overflow check
Artifacts: Maven Central
1.0.7
This release includes some bug fixes along with a new operator and performance enhancements.
Experimental Operator
Note that these APIs may still change or be removed altogether since they are marked as @Experimental
.
withLatestFrom(Observable, Selector)
This allows combining all values from one Observable
with the latest value from a second Observable
at each onNext
.
For example:
Observable<Long> a = Observable.interval(1, TimeUnit.SECONDS);
Observable<Long> b = Observable.interval(250, TimeUnit.MILLISECONDS);
a.withLatestFrom(b, (x, y) -> new long[] { x, y })
.toBlocking()
.forEach(pair -> System.out.println("a: " + pair[0] + " b: " + pair[1]));
This outputs:
a: 0 b: 3
a: 1 b: 6
a: 2 b: 11
a: 3 b: 15
a: 4 b: 19
a: 5 b: 23
a: 6 b: 27
Changes
#2760 Operator: WithLatestFrom
#2762 Optimized isUnsubscribed check
#2759 Observable.using should use unsafeSubscribe and enable eager disposal
#2655 SwitchOnNext: fix upstream producer replacing the ops own producer
Artifacts: Maven Central
1.0.6
This release adds an experimental operator and fixes several bugs.
flatMap(maxConcurrent)
Note that this API may still change or be removed altogether since it is marked as
@Beta
.
A flatMap
overload was added that allows limiting concurrency, or the number of Observable
s being merged .
This now means that these are the same, one using merge
directly, the other using flatMap
and passing in 10
as the maxConcurrent
:
Observable<Observable<Integer>> asyncWork = range(1, 1000000)
.doOnNext(i -> System.out.println("Emitted Value: " + i))
.map(item -> {
return just(item)
.doOnNext(MergeMaxConcurrent::sleep)
.subscribeOn(Schedulers.io());
});
merge(asyncWork, 10).toBlocking().forEach(v -> System.out.println("Received: " + v));
range(1, 1000000)
.doOnNext(i -> System.out.println("Emitted Value: " + i))
.flatMap(item -> {
return just(item)
.doOnNext(MergeMaxConcurrent::sleep)
.subscribeOn(Schedulers.io());
}, 10)
.toBlocking().forEach(v -> System.out.println("Received: " + v));
Changes
- Pull 2627 FlatMap overloads with maximum concurrency parameter
- Pull 2648 TakeWhile: don't unsubscribe downstream.
- Pull 2580 Allow configuring the maximum number of computation scheduler threads
- Pull 2601 Added common Exceptions.throwIfAny to throw a collection of exceptions
- Pull 2644 Missing Unsafe class yields NoClassDefFoundError
- Pull 2642 Fix a potential memory leak in schedulePeriodically
- Pull 2630 Cast back Observer to Subscriber if passed to subscribe(Observer)
- Pull 2622 Changed Observable.empty() into a stateless constant observable.
- Pull 2607 OnSubscribeRefCount - improve comments
Artifacts: Maven Central
1.0.5
This release includes many bug fixes along with a few new operators and enhancements.
Experimental Operators
This release adds a few experimental operators.
Note that these APIs may still change or be removed altogether since they are marked as @Experimental
.
takeUntil(predicate)
This operator allows conditionally unsubscribing an Observable
but inclusively emitting the final onNext
. This differs from takeWhile
which excludes the final onNext
.
// takeUntil(predicate) example
Observable.just(1, 2, 3, 4, 5, 6, 7)
.doOnEach(System.out::println)
.takeUntil(i -> i == 3)
.forEach(System.out::println);
// takeWhile(predicate) example
Observable.just(1, 2, 3, 4, 5, 6, 7)
.doOnEach(System.out::println)
.takeWhile(i -> i <= 3)
.forEach(System.out::println);
This outputs:
// takeUntil(predicate)
[rx.Notification@30e84925 OnNext 1]
1
[rx.Notification@30e84926 OnNext 2]
2
[rx.Notification@30e84927 OnNext 3]
3
// takeWhile(predicate)
[rx.Notification@30e84925 OnNext 1]
1
[rx.Notification@30e84926 OnNext 2]
2
[rx.Notification@30e84927 OnNext 3]
3
[rx.Notification@30e84928 OnNext 4]
Note how takeWhile
produces 4 values and takeUntil
produces 3.
switchIfEmpty
The new switchIfEmpty
operator is a companion to defaultIfEmpty
that switches to a different Observable
if the primary Observable
is empty.
Observable.empty()
.switchIfEmpty(Observable.just(1, 2, 3))
.forEach(System.out::println);
Enhancements
merge(maxConcurrent) with backpressure
This release adds backpressure to merge(maxConcurrent)
so that horizontal buffer bloat can also be controll with the maxConcurrent
parameter.
This allows parallel execution such as the following to work with backpressure:
public class MergeMaxConcurrent {
public static void main(String[] args) {
// define 1,000,000 async tasks
Observable<Observable<Integer>> asyncWork = range(1, 1000000)
.doOnNext(i -> System.out.println("Value: " + i))
.doOnRequest(r -> System.out.println("request1 " + r))
.map(item -> {
return just(item)
// simulate slow IO or computation
.doOnNext(MergeMaxConcurrent::sleep)
.subscribeOn(Schedulers.io());
})
.doOnRequest(r -> System.out.println("request2 " + r));
// allow 10 outstanding tasks at a time
merge(asyncWork, 10).toBlocking().forEach(System.out::println);
}
public static void sleep(int value) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
In prior versions all 1,000,000 tasks are immediately emitted and queued for execution. As of this release it correctly allows 10 at a time to be emitted.
Changes
- Pull 2493 Experimental Operator TakeUntil with predicate
- Pull 2585 Experimental Operator: switchIfEmpty
- Pull 2470 Experimental Subject state information methods & bounded ReplaySubject termination
- Pull 2540 Merge with max concurrency now supports backpressure.
- Pull 2332 Operator retry test fix attempt
- Pull 2244 OperatorTakeLast add check for isUnsubscribed to fast path
- Pull 2469 Remove the execute permission from source files
- Pull 2455 Fix for #2191 - OperatorMulticast fails to unsubscribe from source
- Pull 2474 MergeTest.testConcurrency timeout to let other tests run
- Pull 2335 A set of stateless operators that don't need to be instantiated
- Pull 2447 Fail early if a null subscription is added to a CompositeSubscription.
- Pull 2475 SynchronousQueue.clone fix
- Pull 2477 Backpressure tests fix0121
- Pull 2476 Fixed off-by-one error and value-drop in the window operator.
- Pull 2478 RefCountAsync: adjusted time values as 1 ms is unreliable
- Pull 2238 Fix the bug that cache doesn't unsubscribe the source Observable when the source is terminated
- Pull 1840 Unsubscribe when thread is interrupted
- Pull 2471 Fixes NPEs reported in #1702 by synchronizing queue.
- Pull 2482 Merge: fixed hangs & missed scalar emissions
- Pull 2547 Warnings cleanup
- Pull 2465 ScheduledExecutorService: call purge periodically on JDK 6 to avoid cancelled task-retention
- Pull 2591 Changed the naming of the NewThreadWorker's system parameters
- Pull 2543 OperatorMerge handle request overflow
- Pull 2548 Subscriber.request should throw exception if negative request made
- Pull 2550 Subscriber.onStart requests should be additive (and check for overflow)
- Pull 2553 RxRingBuffer with synchronization
- Pull 2565 Obstruction detection in tests.
- Pull 2563 Retry backpressure test: split error conditions into separate test lines.
- Pull 2572 Give more time to certain concurrency tests.
- Pull 2559 OnSubscribeFromIterable - add request overflow check
- Pull 2574 SizeEviction test needs to return false
- Pull 2561 Updating queue code from JCTools
- Pull 2566 CombineLatest: fixed concurrent requestUpTo yielding -1 requests
- Pull 2552 Publish: fixed incorrect subscriber requested accounting
- Pull 2583 Added perf tests for various container-like subscriptions
- Pull 1955 OnBackpressureXXX: support for common drain manager & fix for former concurrency bugs
- Pull 2590 Zip: fixed unbounded downstream requesting above Long.MAX_VALUE
- Pull 2589 Repeat/retry: fixed unbounded downstream requesting above Long.MAX_VALUE
- Pull 2567 RefCount: disconnect all if upstream terminates
- Pull 2593 Zip: emit onCompleted without waiting for request + avoid re-reading fields
Artifacts: Maven Central
1.0.4
- Pull 2156 Fix the issue that map may swallow fatal exceptions
- Pull 1967 Fix the issue that GroupBy may not call 'unsubscribe'
- Pull 2052 OperatorDoOnRequest.ParentSubscriber should be static class
- Pull 2237 Make Publish Operator Release RingBuffer
- Pull 2053 Fixed wrong bounded ReplaySubject use in test
Artifacts: Maven Central