Skip to content

Different ConnectableObservable behavior in RxJava and RxSwift #5625

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

Closed
Tagakov opened this issue Sep 28, 2017 · 3 comments
Closed

Different ConnectableObservable behavior in RxJava and RxSwift #5625

Tagakov opened this issue Sep 28, 2017 · 3 comments

Comments

@Tagakov
Copy link

Tagakov commented Sep 28, 2017

Recently I discovered a difference in behavior of replay(1).refCount(). In the RxJava when everyone unsubscribes from refCount() the replay(1) loses its state but in the RxSwift the state is preserved and would be emitted to the next subscriber of refCount(). This difference looks odd, but it is present since RxJava 1.x and up to RxJava 2.x. In the process of investigation I found this very strange (for me) puzzle:

    {
        ConnectableObservable<Integer> replay = subject.replay(1);

        Disposable connect = replay.connect();
        subject.onNext(42);
        connect.dispose();

        replay.subscribe(log());
    }

    {
        Observable<Integer> replay = subject.replay(1).refCount();

        Disposable connect = replay.subscribe();
        subject.onNext(24);
        connect.dispose();

        replay.subscribe(log());
    }

In my world there would be no output in console from this code. In the world of my RxSwift colleagues both values, 42 and 24, would be printed out. But reality is different. In RxJava 2.1.4 42 - would be printed and 24 would not.

Somebody can explain to me this strange behavior?

@Tagakov Tagakov changed the title Stragne behavior of ConnectableObservable Strange behavior of ConnectableObservable Sep 28, 2017
@akarnokd
Copy link
Member

The interpretation of what connection and disconnection means is different in these libraries. We largely develop our solutions without much coordination.

In RxJava, the first case disconnects from the subject but the replay remains intact until the next connection, at which point it is reset and starts out empty. Thus, a late subscriber will still get the last item. In the second case, the refCount explicitly resets the replay to its fresh state thus no previous event is preserved.

As far as I know, what you see with RxSwift is similar to the original Rx.NET interpretation: there is an internal ReplaySubject that gets subscribed to the upstream on connect and unsubscribed on disconnection, but otherwise it stays the same instance with the same contents. As long as the main source doesn't complete, you can accumulate data over and over and get all of them replayed.

For a more presistent replay, we have the cache() standard operator and the cacheLast extension operator.

@Tagakov
Copy link
Author

Tagakov commented Sep 28, 2017

Thank you for the explanation and for all of your work, David.

P.S. Maybe it would be worthy to change the title on something more "search-friendly" for the future inquiries, but I can't think of one.

@Tagakov Tagakov closed this as completed Sep 28, 2017
@akarnokd akarnokd changed the title Strange behavior of ConnectableObservable Different ConnectableObservable behavior in RxJava and RxSwift Sep 28, 2017
@artem-zinnatullin
Copy link
Contributor

See #5628 (just cross-linking for discoverability)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants