Skip to content

Replay().RefCount() keeps values after all subscriptions are disposed #1218

@ilnur-nazmutdinov-spark

Description

I use Replay().RefCount() and have several subscribers to it. After all subscribers are unsubscribed original observable stops producing values. After that I subscribe to it again. The new subscriber receives old values of Replay(). It also doesn't have values produced in the interval when there were no subscribers.
For this test:

        [Fact]
        public void RefCount_Replay()
        {
            var subject = new Subject<int>();
            var obs = Observable.Create<int>(subscriber =>
            {
                testOutputHelper.WriteLine("Create");
                var subscription = subject.Do(subscriber.OnNext).Subscribe();
                return () =>
                {
                    subscription.Dispose();
                    testOutputHelper.WriteLine("Dispose");
                };
            });
            var shared = obs
                .Do(val => testOutputHelper.WriteLine($"publish value: {val}"))
                .Replay().RefCount();

            subject.OnNext(1);
            
            testOutputHelper.WriteLine(string.Empty);
            var subscriber1 = shared.Subscribe(val => testOutputHelper.WriteLine($"subscriber #1: {val}"));
            
            subject.OnNext(2);
            
            testOutputHelper.WriteLine(string.Empty);
            var subscriber2 = shared.Subscribe(val => testOutputHelper.WriteLine($"subscriber #2: {val}"));
            
            subject.OnNext(3);
            
            testOutputHelper.WriteLine(string.Empty);
            subscriber1.Dispose();
            subscriber2.Dispose();
            
            subject.OnNext(4);
            
            testOutputHelper.WriteLine(string.Empty);
            var subscriber3 = shared.Subscribe(val => testOutputHelper.WriteLine($"subscriber #3: {val}"));
            
            subject.OnNext(5);
        }

I receive output:

Create
publish value: 2
subscriber #1: 2

subscriber #2: 2
publish value: 3
subscriber #1: 3
subscriber #2: 3

Dispose

subscriber #3: 2
subscriber #3: 3
Create
publish value: 5
subscriber #3: 5

As you can see 3rd subscriber has values 2 and 3 (it also doesn't have value 4).
I expected, that after all subscribers unsubscribed and something subscribes to it again it will start receiving new values and forget old ones. It looks like the problem is that Replay() uses ReplaySubject, but ReplaySubject stores all values when there were any subscribers.
I'm not sure what is the correct behaviour, but I think it either should "forget" old values or it should produce all of them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions