All Downloads are FREE. Search and download functionalities are using the official Maven repository.

reactor.core.publisher.FluxProcessor Maven / Gradle / Ivy

There is a newer version: 5.20.0
Show newest version
/*
 * Copyright (c) 2011-2017 Pivotal Software Inc, All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package reactor.core.publisher;

import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.stream.Stream;

import org.reactivestreams.Processor;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import reactor.core.CoreSubscriber;
import reactor.core.Disposable;
import reactor.core.Scannable;
import reactor.util.annotation.Nullable;

/**
 * A base processor that exposes {@link Flux} API for {@link Processor}.
 *
 * Implementors include {@link UnicastProcessor}, {@link EmitterProcessor},
 * {@link ReplayProcessor}, {@link WorkQueueProcessor} and {@link TopicProcessor}.
 *
 * @author Stephane Maldini
 *
 * @param  the input value type
 * @param  the output value type
 */
public abstract class FluxProcessor extends Flux
		implements Processor, CoreSubscriber, Scannable, Disposable {

	/**
	 * Build a {@link FluxProcessor} whose data are emitted by the most recent emitted {@link Publisher}.
	 * The {@link Flux} will complete once both the publishers source and the last switched to {@link Publisher} have
	 * completed.
	 *
	 * 

* * * @param the produced type * @return a {@link FluxProcessor} accepting publishers and producing T */ public static FluxProcessor, T> switchOnNext() { UnicastProcessor> emitter = UnicastProcessor.create(); FluxProcessor, T> p = FluxProcessor.wrap(emitter, switchOnNext(emitter)); return p; } /** * Transform a receiving {@link Subscriber} and a producing {@link Publisher} in a logical {@link FluxProcessor}. * The link between the passed upstream and returned downstream will not be created automatically, e.g. not * subscribed together. A {@link Processor} might choose to have orthogonal sequence input and output. * * @param the receiving type * @param the producing type * * @param upstream the upstream subscriber * @param downstream the downstream publisher * @return a new blackboxed {@link FluxProcessor} */ public static FluxProcessor wrap(final Subscriber upstream, final Publisher downstream) { return new DelegateProcessor<>(downstream, upstream); } @Override public void dispose() { onError(new CancellationException("Disposed")); } /** * Return the number of active {@link Subscriber} or {@literal -1} if untracked. * * @return the number of active {@link Subscriber} or {@literal -1} if untracked */ public long downstreamCount(){ return inners().count(); } /** * Return the processor buffer capacity if any or {@link Integer#MAX_VALUE} * * @return processor buffer capacity if any or {@link Integer#MAX_VALUE} */ public int getBufferSize() { return Integer.MAX_VALUE; } /** * Current error if any, default to null * * @return Current error if any, default to null */ @Nullable public Throwable getError() { return null; } /** * Return true if any {@link Subscriber} is actively subscribed * * @return true if any {@link Subscriber} is actively subscribed */ public boolean hasDownstreams() { return downstreamCount() != 0L; } /** * Return true if terminated with onComplete * * @return true if terminated with onComplete */ public final boolean hasCompleted() { return isTerminated() && getError() == null; } /** * Return true if terminated with onError * * @return true if terminated with onError */ public final boolean hasError() { return isTerminated() && getError() != null; } @Override public Stream inners() { return Stream.empty(); } /** * Has this upstream finished or "completed" / "failed" ? * * @return has this upstream finished or "completed" / "failed" ? */ public boolean isTerminated() { return false; } /** * Return true if this {@link FluxProcessor} supports multithread producing * * @return true if this {@link FluxProcessor} supports multithread producing */ public boolean isSerialized() { return false; } @Override @Nullable public Object scanUnsafe(Attr key) { if (key == Attr.TERMINATED) return isTerminated(); if (key == Attr.ERROR) return getError(); if (key == Attr.CAPACITY) return getBufferSize(); return null; } /** * Create a {@link FluxProcessor} that safely gates multi-threaded producer * {@link Subscriber#onNext(Object)}. * * @return a serializing {@link FluxProcessor} */ public final FluxProcessor serialize() { return new DelegateProcessor<>(this, Operators.serialize(this)); } /** * Create a {@link FluxSink} that safely gates multi-threaded producer * {@link Subscriber#onNext(Object)}. This processor will be subscribed to * that {@link FluxSink}, and any previous subscribers will be unsubscribed. * *

The returned {@link FluxSink} will not apply any * {@link FluxSink.OverflowStrategy} and overflowing {@link FluxSink#next(Object)} * will behave in two possible ways depending on the Processor: *

    *
  • an unbounded processor will handle the overflow itself by dropping or * buffering
  • *
  • a bounded processor will block/spin
  • *
* * @return a serializing {@link FluxSink} */ public final FluxSink sink() { return sink(FluxSink.OverflowStrategy.IGNORE); } /** * Create a {@link FluxSink} that safely gates multi-threaded producer * {@link Subscriber#onNext(Object)}. This processor will be subscribed to * that {@link FluxSink}, and any previous subscribers will be unsubscribed. * *

The returned {@link FluxSink} will not apply any * {@link FluxSink.OverflowStrategy} and overflowing {@link FluxSink#next(Object)} * will behave in two possible ways depending on the Processor: *

    *
  • an unbounded processor will handle the overflow itself by dropping or * buffering
  • *
  • a bounded processor will block/spin on IGNORE strategy, or apply the * strategy behavior
  • *
* * @param strategy the overflow strategy, see {@link FluxSink.OverflowStrategy} * for the * available strategies * @return a serializing {@link FluxSink} */ public final FluxSink sink(FluxSink.OverflowStrategy strategy) { Objects.requireNonNull(strategy, "strategy"); if (getBufferSize() == Integer.MAX_VALUE){ strategy = FluxSink.OverflowStrategy.IGNORE; } FluxCreate.BaseSink s = FluxCreate.createSink(this, strategy); onSubscribe(s); if(s.isCancelled() || (isSerialized() && getBufferSize() == Integer.MAX_VALUE)){ return s; } if (serializeAlways()) return new FluxCreate.SerializedSink<>(s); else return new FluxCreate.SerializeOnRequestSink<>(s); } /** * Returns serialization strategy. If true, {@link FluxProcessor#sink()} will always * be serialized. Otherwise sink is serialized only if {@link FluxSink#onRequest(java.util.function.LongConsumer)} * is invoked. * @return true to serialize any sink, false to delay serialization till onRequest */ protected boolean serializeAlways() { return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy