use of reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST in project reactor-core by reactor.
the class FluxSpecTests method acceptedErrorsArePassedToRegisteredConsumer.
@Test
public void acceptedErrorsArePassedToRegisteredConsumer() {
// "Accepted errors are passed to a registered Consumer"
// given: "a composable with a registered consumer of RuntimeExceptions"
Sinks.Many<Integer> composable = Sinks.many().multicast().onBackpressureBuffer();
LongAdder errors = new LongAdder();
composable.asFlux().doOnError(e -> errors.increment()).subscribe();
// when: "A RuntimeException is accepted"
composable.emitError(new RuntimeException(), FAIL_FAST);
// then: "it is passed to the consumer"
assertThat(errors.intValue()).isEqualTo(1);
// when: "A new error consumer is subscribed"
Flux.error(new RuntimeException()).doOnError(e -> errors.increment()).subscribe();
// then: "it is called since publisher is in error state"
assertThat(errors.intValue()).isEqualTo(2);
}
use of reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST in project reactor-core by reactor.
the class FluxUsingTest method subscriberCancels.
@Test
public void subscriberCancels() {
AssertSubscriber<Integer> ts = AssertSubscriber.create();
AtomicInteger cleanup = new AtomicInteger();
Sinks.Many<Integer> tp = Sinks.unsafe().many().multicast().directBestEffort();
Flux.using(() -> 1, r -> tp.asFlux(), cleanup::set, true).subscribe(ts);
assertThat(tp.currentSubscriberCount()).as("tp has subscriber").isPositive();
tp.emitNext(1, FAIL_FAST);
ts.assertValues(1).assertNotComplete().assertNoError();
ts.cancel();
tp.emitNext(2, FAIL_FAST);
ts.assertValues(1).assertNotComplete().assertNoError();
assertThat(tp.currentSubscriberCount()).as("tp has subscriber").isZero();
assertThat(cleanup).hasValue(1);
}
use of reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST in project reactor-core by reactor.
the class FluxFlatMapTest method flatMapUnbounded.
@Test
public void flatMapUnbounded() {
AssertSubscriber<Integer> ts = AssertSubscriber.create();
AtomicInteger emission = new AtomicInteger();
Flux<Integer> source = Flux.range(1, 1000).doOnNext(v -> emission.getAndIncrement());
Sinks.Many<Integer> source1 = Sinks.many().multicast().onBackpressureBuffer();
Sinks.Many<Integer> source2 = Sinks.many().multicast().onBackpressureBuffer();
source.flatMap(v -> v == 1 ? source1.asFlux() : source2.asFlux(), Integer.MAX_VALUE, 32).subscribe(ts);
assertThat(emission).hasValue(1000);
ts.assertNoValues().assertNoError().assertNotComplete();
assertThat(source1.currentSubscriberCount()).as("source1 has subscriber").isPositive();
assertThat(source2.currentSubscriberCount()).as("source2 has subscriber").isPositive();
source1.emitNext(1, FAIL_FAST);
source1.emitComplete(FAIL_FAST);
source2.emitNext(2, FAIL_FAST);
source2.emitComplete(FAIL_FAST);
ts.assertValueCount(1000).assertNoError().assertComplete();
}
use of reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST in project reactor-core by reactor.
the class FluxFlatMapTest method singleSubscriberOnly.
@Test
public void singleSubscriberOnly() {
AssertSubscriber<Integer> ts = AssertSubscriber.create();
AtomicInteger emission = new AtomicInteger();
Flux<Integer> source = Flux.range(1, 2).doOnNext(v -> emission.getAndIncrement());
Sinks.Many<Integer> source1 = Sinks.many().multicast().onBackpressureBuffer();
Sinks.Many<Integer> source2 = Sinks.many().multicast().onBackpressureBuffer();
source.flatMap(v -> v == 1 ? source1.asFlux() : source2.asFlux(), 1, 32).subscribe(ts);
assertThat(emission).hasValue(1);
ts.assertNoValues().assertNoError().assertNotComplete();
assertThat(source1.currentSubscriberCount()).as("source1 has subscriber").isPositive();
assertThat(source2.currentSubscriberCount()).as("source2 has subscriber").isZero();
source1.emitNext(1, FAIL_FAST);
source2.emitNext(10, FAIL_FAST);
source1.emitComplete(FAIL_FAST);
source2.emitNext(2, FAIL_FAST);
source2.emitComplete(FAIL_FAST);
ts.assertValues(1, 10, 2).assertNoError().assertComplete();
}
use of reactor.core.publisher.Sinks.EmitFailureHandler.FAIL_FAST in project reactor-core by reactor.
the class FluxTests method multiplexUsingDispatchersAndSplit.
/**
* <pre>
* forkStream
* / \ < - - - int
* v v
* persistenceStream computationStream
* \ / < - - - List< String >
* v v
* joinStream < - - - String
* splitStream
* observedSplitStream
* </pre>
*/
@Test
@Timeout(10)
public void multiplexUsingDispatchersAndSplit() {
final Sinks.Many<Integer> forkEmitterProcessor = Sinks.many().multicast().onBackpressureBuffer();
final Sinks.Many<Integer> computationEmitterProcessor = Sinks.unsafe().many().multicast().onBackpressureBuffer(256, false);
Scheduler computation = afterTest.autoDispose(Schedulers.newSingle("computation"));
Scheduler persistence = afterTest.autoDispose(Schedulers.newSingle("persistence"));
Scheduler forkJoin = afterTest.autoDispose(Schedulers.newParallel("forkJoin", 2));
final Flux<List<String>> computationStream = computationEmitterProcessor.asFlux().publishOn(computation).map(i -> {
final List<String> list = new ArrayList<>(i);
for (int j = 0; j < i; j++) {
list.add("i" + j);
}
return list;
}).doOnNext(ls -> println("Computed: ", ls)).log("computation");
final Sinks.Many<Integer> persistenceEmitterProcessor = Sinks.unsafe().many().multicast().onBackpressureBuffer(Queues.SMALL_BUFFER_SIZE, false);
final Flux<List<String>> persistenceStream = persistenceEmitterProcessor.asFlux().publishOn(persistence).doOnNext(i -> println("Persisted: ", i)).map(i -> Collections.singletonList("done" + i)).log("persistence");
Flux<Integer> forkStream = forkEmitterProcessor.asFlux().publishOn(forkJoin).log("fork");
// from(sink) calls below should return same instance since both processor and standalone sink
forkStream.subscribe(v -> computationEmitterProcessor.emitNext(v, FAIL_FAST), e -> computationEmitterProcessor.emitError(e, FAIL_FAST), () -> computationEmitterProcessor.emitComplete(FAIL_FAST));
forkStream.subscribe(v -> persistenceEmitterProcessor.emitNext(v, FAIL_FAST), e -> persistenceEmitterProcessor.emitError(e, FAIL_FAST), () -> persistenceEmitterProcessor.emitComplete(FAIL_FAST));
final Flux<List<String>> joinStream = Flux.zip(computationStream, persistenceStream, (a, b) -> Arrays.asList(a, b)).publishOn(forkJoin).map(listOfLists -> {
listOfLists.get(0).addAll(listOfLists.get(1));
return listOfLists.get(0);
}).log("join");
final Semaphore doneSemaphore = new Semaphore(0);
StepVerifier.create(joinStream.flatMap(Flux::fromIterable).log("resultStream").collectList().doOnTerminate(doneSemaphore::release)).then(() -> {
forkEmitterProcessor.emitNext(1, FAIL_FAST);
forkEmitterProcessor.emitNext(2, FAIL_FAST);
forkEmitterProcessor.emitNext(3, FAIL_FAST);
forkEmitterProcessor.emitComplete(FAIL_FAST);
}).assertNext(res -> assertThat(res).containsExactly("i0", "done1", "i0", "i1", "done2", "i0", "i1", "i2", "done3")).verifyComplete();
}
Aggregations