FluxMergeSequential(Flux<? extends T> source, Function<? super T, ? extends Publisher<? extends R>> mapper, int maxConcurrency, int prefetch, ErrorMode errorMode) { this(source, mapper, maxConcurrency, prefetch, errorMode, Queues.get(Math.max(prefetch, maxConcurrency))); }
EqualSubscriber(EqualCoordinator<T> parent, int prefetch) { this.parent = parent; this.prefetch = prefetch; this.queue = Queues.<T>get(prefetch).get(); }
/** * Merges the values from each 'rail', but choose which one to merge by way of a * provided {@link Comparator}, picking the smallest of all rails. The result is * exposed back as a {@link Flux}. * * @param comparator the comparator to choose the smallest value available from all rails * @param prefetch the prefetch to use * @return the new Flux instance * * @see ParallelFlux#ordered(Comparator) */ public final Flux<T> ordered(Comparator<? super T> comparator, int prefetch) { return new ParallelMergeOrdered<>(this, prefetch, Queues.get(prefetch), comparator); }
@SafeVarargs static <I> Flux<I> merge(int prefetch, boolean delayError, Publisher<? extends I>... sources) { if (sources.length == 0) { return empty(); } if (sources.length == 1) { return from(sources[0]); } return onAssembly(new FluxMerge<>(sources, delayError, sources.length, Queues.get(sources.length), prefetch, Queues.get(prefetch))); }
/** * Merges the values from each 'rail' in a round-robin or same-order fashion and * exposes it as a regular Publisher sequence, running with a give prefetch value for * the rails. * * @param prefetch the prefetch amount to use for each rail * * @return the new Flux instance */ public final Flux<T> sequential(int prefetch) { return Flux.onAssembly(new ParallelMergeSequential<>(this, prefetch, Queues.get(prefetch))); }
/** * Shares a sequence for the duration of a function that may transform it and * consume it as many times as necessary without causing multiple subscriptions * to the upstream. * * @param transform the transformation function * @param prefetch the request size * @param <R> the output value type * * @return a new {@link Flux} */ public final <R> Flux<R> publish(Function<? super Flux<T>, ? extends Publisher<? extends R>> transform, int prefetch) { return onAssembly(new FluxPublishMulticast<>(this, transform, prefetch, Queues .get(prefetch))); }
@Test public void capacityReactorBoundedQueue() { //the bounded queue floors at 8 and rounds to the next power of 2 assertThat(Queues.capacity(Queues.get(2).get())) .isEqualTo(8); assertThat(Queues.capacity(Queues.get(8).get())) .isEqualTo(8); assertThat(Queues.capacity(Queues.get(9).get())) .isEqualTo(16); }
@Test public void bufferSizeReactorBoundedQueue() { //the bounded queue floors at 8 and rounds to the next power of 2 assertThat(UnicastProcessor.create(Queues.get(2).get()) .getBufferSize()) .isEqualTo(8); assertThat(UnicastProcessor.create(Queues.get(8).get()) .getBufferSize()) .isEqualTo(8); assertThat(UnicastProcessor.create(Queues.get(9).get()) .getBufferSize()) .isEqualTo(16); }
@Test public void scanMainLargeBuffered() { CoreSubscriber<Integer> actual = new LambdaSubscriber<>(null, e -> {}, null, null); FluxFlatMap.FlatMapMain<Integer, Integer> test = new FluxFlatMap.FlatMapMain<>(actual, i -> Mono.just(i), true, 5, Queues.<Integer>unbounded(), 789, Queues.<Integer>get(789)); test.scalarQueue = new ConcurrentLinkedQueue<>(); test.scalarQueue.add(1); test.scalarQueue.add(2); test.scalarQueue.add(3); test.size = Integer.MAX_VALUE; assertThat(test.scan(Scannable.Attr.BUFFERED)).isEqualTo(Integer.MIN_VALUE); assertThat(test.scan(Scannable.Attr.LARGE_BUFFERED)).isEqualTo(Integer.MAX_VALUE + 3L); }
@Test public void createOverrideQueue() { Queue<Integer> queue = Queues.<Integer>get(10).get(); UnicastProcessor<Integer> processor = UnicastProcessor.create(queue); assertProcessor(processor, queue, null, null); }
@Test public void createOverrideQueueOnTerminate() { Disposable onTerminate = () -> {}; Queue<Integer> queue = Queues.<Integer>get(10).get(); UnicastProcessor<Integer> processor = UnicastProcessor.create(queue, onTerminate); assertProcessor(processor, queue, null, onTerminate); }
@Test public void createOverrideAll() { Disposable onTerminate = () -> {}; Consumer<? super Integer> onOverflow = t -> {}; Queue<Integer> queue = Queues.<Integer>get(10).get(); UnicastProcessor<Integer> processor = UnicastProcessor.create(queue, onOverflow, onTerminate); assertProcessor(processor, queue, onOverflow, onTerminate); }
@Test public void discardDelayedOnNextQueueReject() { List<Object> discarded = new ArrayList<>(); AssertSubscriber<Object> testSubscriber = new AssertSubscriber<>( Context.of(Hooks.KEY_ON_DISCARD, (Consumer<?>) discarded::add)); final CoreSubscriber<Object> subscriber = FluxConcatMap.subscriber(testSubscriber, Mono::just, Queues.get(0), 1, FluxConcatMap.ErrorMode.END); subscriber.onSubscribe(Operators.emptySubscription()); subscriber.onNext(1); assertThat(discarded).containsExactly(1); }
@Test public void discardOnNextQueueReject() { List<Object> discarded = new ArrayList<>(); AssertSubscriber<Object> discardSubscriber = new AssertSubscriber<>( Context.of(Hooks.KEY_ON_DISCARD, (Consumer<?>) discarded::add)); final CoreSubscriber<Object> subscriber = FluxConcatMap.subscriber(discardSubscriber, Mono::just, Queues.get(0), 1, FluxConcatMap.ErrorMode.IMMEDIATE); subscriber.onSubscribe(Operators.emptySubscription()); subscriber.onNext(1); assertThat(discarded).containsExactly(1); }
@Test public void threadBoundaryPreventsInvalidFusionFilter() { UnicastProcessor<Integer> up = UnicastProcessor.create(Queues.<Integer>get(2).get()); String s = Thread.currentThread() .getName(); AssertSubscriber<Integer> ts = AssertSubscriber.create(); up.filter(v -> s.equals(Thread.currentThread() .getName())) .publishOn(Schedulers.fromExecutorService(exec)) .subscribe(ts); up.onNext(1); up.onComplete(); ts.await(Duration.ofSeconds(5)); ts.assertValues(1) .assertNoError() .assertComplete(); }
@Test public void asyncFusionAvailable() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); UnicastProcessor.create(Queues.<Integer>get(2).get()) .doOnNext(v -> { }) .subscribe(ts); Subscription s = ts.upstream(); Assert.assertTrue("Non-fuseable upstream" + s, s instanceof Fuseable.QueueSubscription); }
@Test public void asyncFusionAvailable() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); UnicastProcessor.create(Queues.<Integer>get(2).get()) .doOnNext(v -> { }) .subscribe(ts); Subscription s = ts.upstream(); Assert.assertTrue("Non-fuseable upstream" + s, s instanceof Fuseable.QueueSubscription); }
@Test public void asyncFusionMapToNull() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); UnicastProcessor<Integer> up = UnicastProcessor.create(Queues.<Integer>get(2).get()); up.onNext(1); up.onNext(2); up.onComplete(); up.map(v -> v == 2 ? null : v) .concatMap(Flux::just) .subscribe(ts); ts.assertValues(1) .assertError(NullPointerException.class) .assertNotComplete(); }
@Test public void asyncFusionMapToNullFilter() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); UnicastProcessor<Integer> up = UnicastProcessor.create(Queues.<Integer>get(2).get()); up.onNext(1); up.onNext(2); up.onComplete(); up.map(v -> v == 2 ? null : v) .filter(v -> true) .concatMap(Flux::just) .subscribe(ts); ts.assertValues(1) .assertError(NullPointerException.class) .assertNotComplete(); }