reactor / reactor-core

Non-Blocking Reactive Foundation for the JVM

Home Page:http://projectreactor.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Flux share method feature

Nuclear-Liu opened this issue · comments

Expected Behavior

When subscribing to a flux(Flux::share), you should only get results that have not yet been published.

Actual Behavior

When subscribing to a flux, all data is playback

Steps to Reproduce

@Test
void testShareBug() throws InterruptedException {
    Flux<Integer> coldFlux = Flux.range(1, 7)
            .delayElements(Duration.ofMillis(100))
            /*.doOnNext(System.out::println)*/;
    Flux<Integer> shareSource = coldFlux.share();
    TimeUnit.MILLISECONDS.sleep(300);
    shareSource.subscribe(item -> System.out.println("sub1 data:" + item));
    TimeUnit.MILLISECONDS.sleep(100);
    shareSource.subscribe(item -> System.out.println("sub2 data:" + item));
    TimeUnit.MILLISECONDS.sleep(2000);
}
  • Expected:
sub1 data:3
sub1 data:4
sub2 data:4
sub1 data:5
sub2 data:5
sub1 data:6
sub2 data:6
sub1 data:7
sub2 data:7
  • Actual
sub1 data:1
sub2 data:1
sub1 data:2
sub2 data:2
sub1 data:3
sub2 data:3
sub1 data:4
sub2 data:4
sub1 data:5
sub2 data:5
sub1 data:6
sub2 data:6
sub1 data:7
sub2 data:7

Possible Solution

Your Environment

  • Reactor version(s) used: 3.6.3
  • Other relevant libraries versions (eg. netty, ...):
  • JVM version (java -version): OpenJDK 21
  • OS and version (eg uname -a): Windows 11

Hey @Nuclear-Liu 👋

What you see is the expected behaviour. Your assumption has one shortcoming – you expect the source to emit without any Subscriber (as you start counting the time assuming items are silently dropped). Please consult the javadoc of the share() operator, which stands for a shorthand of publish().refCount(). This means that the initial subscription happens when the first subscriber appears. If we modify your example in the following way:

	Flux<Integer> coldFlux = Flux.range(1, 7)
	                             .delayElements(Duration.ofMillis(100))
			/*.doOnNext(System.out::println)*/;
	Flux<Integer> shareSource = coldFlux.share();
	// Nothing happens yet! Only after the following call:
	shareSource.subscribe(item -> System.out.println("sub1 data:" + item));
	// Now, during the 350ms 3 items are consumed by sub1
	TimeUnit.MILLISECONDS.sleep(350);
	// sub2 arrives 350ms into the sub1's subscription and in 50ms will receive item 4!
	shareSource.subscribe(item -> System.out.println("sub2 data:" + item));
	TimeUnit.MILLISECONDS.sleep(2000);

The output is as follows:

sub1 data:1
sub1 data:2
sub1 data:3
sub1 data:4
sub2 data:4
sub1 data:5
sub2 data:5
sub1 data:6
sub2 data:6
sub1 data:7
sub2 data:7

I'm closing this issue as invalid. Please consider StackOverflow in the future if you have further questions.

Thinks!