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

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

Go to download

Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava3/Reactive API. Client side caching. Over 50 Redis based Java objects and services: JCache API, Apache Tomcat, Hibernate, Spring, Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Scheduler, RPC

There is a newer version: 3.40.2
Show newest version
/*
 * Copyright (c) 2020-2022 VMware Inc. or its affiliates, 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
 *
 *   https://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.time.Duration;
import java.util.Queue;

import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;

import reactor.core.Disposable;
import reactor.core.Exceptions;
import reactor.core.Scannable;
import reactor.core.scheduler.Scheduler;
import reactor.util.annotation.Nullable;
import reactor.util.concurrent.Queues;
import reactor.util.context.Context;

/**
 * Sinks are constructs through which Reactive Streams signals can be programmatically pushed, with {@link Flux} or {@link Mono}
 * semantics. These standalone sinks expose {@link Many#tryEmitNext(Object) tryEmit} methods that return an {@link EmitResult} enum,
 * allowing to atomically fail in case the attempted signal is inconsistent with the spec and/or the state of the sink.
 * 

* This class exposes a collection of ({@link Sinks.Many} builders and {@link Sinks.One} factories. Unless constructed through the * {@link #unsafe()} spec, these sinks are thread safe in the sense that they will detect concurrent access and fail fast on one of * the attempts. {@link #unsafe()} sinks on the other hand are expected to be externally synchronized (typically by being called from * within a Reactive Streams-compliant context, like a {@link Subscriber} or an operator, which means it is ok to remove the overhead * of detecting concurrent access from the sink itself). * * @author Simon Baslé * @author Stephane Maldini */ public final class Sinks { private Sinks() { } /** * A {@link Sinks.Empty} which exclusively produces one terminal signal: error or complete. * It has the following characteristics: *

    *
  • Multicast
  • *
  • Backpressure : this sink does not need any demand since it can only signal error or completion
  • *
  • Replaying: Replay the terminal signal (error or complete).
  • *
* Use {@link Sinks.Empty#asMono()} to expose the {@link Mono} view of the sink to downstream consumers. * * @return a new {@link Sinks.Empty} * @see RootSpec#empty() */ public static Sinks.Empty empty() { return SinksSpecs.DEFAULT_SINKS.empty(); } /** * A {@link Sinks.One} that works like a conceptual promise: it can be completed * with or without a value at any time, but only once. This completion is replayed to late subscribers. * Calling {@link One#tryEmitValue(Object)} (or {@link One#emitValue(Object, Sinks.EmitFailureHandler)}) is enough and will * implicitly produce a {@link Subscriber#onComplete()} signal as well. *

* Use {@link One#asMono()} to expose the {@link Mono} view of the sink to downstream consumers. * * @return a new {@link Sinks.One} * @see RootSpec#one() */ public static Sinks.One one() { return SinksSpecs.DEFAULT_SINKS.one(); } /** * Help building {@link Sinks.Many} sinks that will broadcast multiple signals to one or more {@link Subscriber}. *

* Use {@link Many#asFlux()} to expose the {@link Flux} view of the sink to the downstream consumers. * * @return {@link ManySpec} * @see RootSpec#many() */ public static ManySpec many() { return SinksSpecs.DEFAULT_SINKS.many(); } /** * Return a {@link RootSpec root spec} for more advanced use cases such as building operators. * Unsafe {@link Sinks.Many}, {@link Sinks.One} and {@link Sinks.Empty} are not serialized nor thread safe, * which implies they MUST be externally synchronized so as to respect the Reactive Streams specification. * This can typically be the case when the sinks are being called from within a Reactive Streams-compliant context, * like a {@link Subscriber} or an operator. In turn, this allows the sinks to have less overhead, since they * don't care to detect concurrent access anymore. * * @return {@link RootSpec} */ public static RootSpec unsafe() { return SinksSpecs.UNSAFE_ROOT_SPEC; } /** * Represents the immediate result of an emit attempt (eg. in {@link Sinks.Many#tryEmitNext(Object)}. * This does not guarantee that a signal is consumed, it simply refers to the sink state when an emit method is invoked. * This is a particularly important distinction with regard to {@link #FAIL_CANCELLED} which means the sink is -now- * interrupted and emission can't proceed. Consequently, it is possible to emit a signal and obtain an "OK" status even * if an in-flight cancellation is happening. This is due to the async nature of these actions: producer emits while * consumer can interrupt independently. */ public enum EmitResult { /** * Has successfully emitted the signal */ OK, /** * Has failed to emit the signal because the sink was previously terminated successfully or with an error */ FAIL_TERMINATED, /** * Has failed to emit the signal because the sink does not have buffering capacity left */ FAIL_OVERFLOW, /** * Has failed to emit the signal because the sink was previously interrupted by its consumer */ FAIL_CANCELLED, /** * Has failed to emit the signal because the access was not serialized */ FAIL_NON_SERIALIZED, /** * Has failed to emit the signal because the sink has never been subscribed to has no capacity * to buffer the signal. */ FAIL_ZERO_SUBSCRIBER; /** * Represents a successful emission of a signal. *

* This is more future-proof than checking for equality with {@code OK} since * new OK-like codes could be introduced later. */ public boolean isSuccess() { return this == OK; } /** * Represents a failure to emit a signal. */ public boolean isFailure() { return this != OK; } /** * Easily convert from an {@link EmitResult} to throwing an exception on {@link #isFailure() failure cases}. * This is useful if throwing is the most relevant way of dealing with a failed emission attempt. * Note however that generally Reactor code doesn't favor throwing exceptions but rather propagating * them through onError signals. * See also {@link #orThrowWithCause(Throwable)} in case of an {@link One#tryEmitError(Throwable) emitError} * failure for which you want to attach the originally pushed {@link Exception}. * * @see #orThrowWithCause(Throwable) */ public void orThrow() { if (this == OK) return; throw new EmissionException(this); } /** * Easily convert from an {@link EmitResult} to throwing an exception on {@link #isFailure() failure cases}. * This is useful if throwing is the most relevant way of dealing with failed {@link One#tryEmitError(Throwable) tryEmitError} * attempt, in which case you probably wants to propagate the originally pushed {@link Exception}. * Note however that generally Reactor code doesn't favor throwing exceptions but rather propagating * them through onError signals. * * @see #orThrow() */ public void orThrowWithCause(Throwable cause) { if (this == OK) return; throw new EmissionException(cause, this); } } /** * An exception representing a {@link EmitResult#isFailure() failed} {@link EmitResult}. * The exact type of failure can be found via {@link #getReason()}. */ public static final class EmissionException extends IllegalStateException { final EmitResult reason; public EmissionException(EmitResult reason) { this(reason, "Sink emission failed with " + reason); } public EmissionException(Throwable cause, EmitResult reason) { super("Sink emission failed with " + reason, cause); this.reason = reason; } public EmissionException(EmitResult reason, String message) { super(message); this.reason = reason; } /** * Get the failure {@link EmitResult} code that is represented by this exception. * * @return the {@link EmitResult} */ public EmitResult getReason() { return this.reason; } } /** * * @author Animesh Chaturvedi */ static class OptimisticEmitFailureHandler implements EmitFailureHandler { private final long deadline; OptimisticEmitFailureHandler(Duration duration){ this.deadline = System.nanoTime() + duration.toNanos(); } @Override public boolean onEmitFailure(SignalType signalType, EmitResult emitResult) { return emitResult.equals(Sinks.EmitResult.FAIL_NON_SERIALIZED) && (System.nanoTime() < this.deadline); } } /** * A handler supporting the emit API (eg. {@link Many#emitNext(Object, Sinks.EmitFailureHandler)}), * checking non-successful emission results from underlying {@link Many#tryEmitNext(Object) tryEmit} * API calls to decide whether or not such calls should be retried. * Other than instructing to retry, the handlers are allowed to have side effects * like parking the current thread for longer retry loops. They don't, however, influence the * exact action taken by the emit API implementations when the handler doesn't allow * the retry to occur. * * @implNote It is expected that the handler may perform side effects (e.g. busy looping) * and should not be considered a plain {@link java.util.function.Predicate}. */ public interface EmitFailureHandler { /** * A pre-made handler that will not instruct to retry any failure * and trigger the failure handling immediately. */ EmitFailureHandler FAIL_FAST = (signalType, emission) -> false; /** * Create an {@link EmitFailureHandler} which will busy loop in case of concurrent use * of the sink ({@link EmitResult#FAIL_NON_SERIALIZED}, up to a deadline. * The deadline is computed immediately from the current time (construction time) * + provided {@link Duration}. *

* As a result there will always be some delay between this computation and the actual first * use of the handler (at a minimum, the time it takes for the first sink emission attempt). * Consider this when choosing the {@link Duration}, and probably prefer something above 100ms, * and don't cache the returning handler for later usage. * * @param duration {@link Duration} for the deadline * @return an optimistic and bounded busy-looping {@link EmitFailureHandler} */ static EmitFailureHandler busyLooping(Duration duration){ return new OptimisticEmitFailureHandler(duration); } /** * Decide whether the emission should be retried, depending on the provided {@link EmitResult} * and the type of operation that was attempted (represented as a {@link SignalType}). * Side effects are allowed. * * @param signalType the signal that triggered the emission. Can be either {@link SignalType#ON_NEXT}, {@link SignalType#ON_ERROR} or {@link SignalType#ON_COMPLETE}. * @param emitResult the result of the emission (a failure) * @return {@code true} if the operation should be retried, {@code false} otherwise. */ boolean onEmitFailure(SignalType signalType, EmitResult emitResult); } //implementation note: this should now only be implemented by the Sinks.unsafe() path /** * Provides a choice of {@link Sinks.One}/{@link Sinks.Empty} factories and * {@link Sinks.ManySpec further specs} for {@link Sinks.Many}. */ public interface RootSpec { /** * A {@link Sinks.Empty} which exclusively produces one terminal signal: error or complete. * It has the following characteristics: *

    *
  • Multicast
  • *
  • Backpressure : this sink does not need any demand since it can only signal error or completion
  • *
  • Replaying: Replay the terminal signal (error or complete).
  • *
* Use {@link Sinks.Empty#asMono()} to expose the {@link Mono} view of the sink to downstream consumers. */ Sinks.Empty empty(); /** * A {@link Sinks.One} that works like a conceptual promise: it can be completed * with or without a value at any time, but only once. This completion is replayed to late subscribers. * Calling {@link One#emitValue(Object, Sinks.EmitFailureHandler)} (or * {@link One#tryEmitValue(Object)}) is enough and will implicitly produce * a {@link Subscriber#onComplete()} signal as well. *

* Use {@link One#asMono()} to expose the {@link Mono} view of the sink to downstream consumers. */ Sinks.One one(); /** * Help building {@link Sinks.Many} sinks that will broadcast multiple signals to one or more {@link Subscriber}. *

* Use {@link Many#asFlux()} to expose the {@link Flux} view of the sink to the downstream consumers. * * @return {@link ManySpec} */ ManySpec many(); /** * Help building {@link Sinks.ManyWithUpstream} sinks that can also be {@link ManyWithUpstream#subscribeTo(Publisher) subscribed to} * an upstream {@link Publisher}. This is an advanced use case, see {@link ManyWithUpstream#subscribeTo(Publisher)}. * * @return a {@link ManyWithUpstreamUnsafeSpec} */ ManyWithUpstreamUnsafeSpec manyWithUpstream(); } /** * Provides {@link Sinks.Many} specs for sinks which can emit multiple elements */ public interface ManySpec { /** * Help building {@link Sinks.Many} that will broadcast signals to a single {@link Subscriber} * * @return {@link UnicastSpec} */ UnicastSpec unicast(); /** * Help building {@link Sinks.Many} that will broadcast signals to multiple {@link Subscriber} * * @return {@link MulticastSpec} */ MulticastSpec multicast(); /** * Help building {@link Sinks.Many} that will broadcast signals to multiple {@link Subscriber} with the ability to retain * and replay all or an arbitrary number of elements. * * @return {@link MulticastReplaySpec} */ MulticastReplaySpec replay(); } /** * Instead of {@link Sinks#unsafe() unsafe} flavors of {@link Sinks.Many}, this spec provides {@link ManyWithUpstream} * implementations. These additionally support being subscribed to an upstream {@link Publisher}, at most once. * Please note that when this is done, one MUST stop using emit/tryEmit APIs, reserving signal creation to be the * sole responsibility of the upstream {@link Publisher}. *

* As the number of such implementations is deliberately kept low, this spec doesn't further distinguish between * multicast/unicast/replay categories other than in method naming. */ public interface ManyWithUpstreamUnsafeSpec { /** * A {@link Sinks.ManyWithUpstream} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: warm up. Remembers up to {@link Queues#SMALL_BUFFER_SIZE} * elements pushed via {@link Many#tryEmitNext(Object)} before the first {@link Subscriber} is registered.
  • *
  • Backpressure : this sink honors downstream demand by conforming to the lowest demand in case * of multiple subscribers.
    If the difference between multiple subscribers is greater than {@link Queues#SMALL_BUFFER_SIZE}: *
    • {@link Many#tryEmitNext(Object) tryEmitNext} will return {@link EmitResult#FAIL_OVERFLOW}
    • *
    • {@link Many#emitNext(Object, Sinks.EmitFailureHandler) emitNext} will terminate the sink by {@link Many#emitError(Throwable, Sinks.EmitFailureHandler) emitting} * an {@link Exceptions#failWithOverflow() overflow error}.
    *
  • *
  • Replaying: No replay of values seen by earlier subscribers. Only forwards to a {@link Subscriber} * the elements that have been pushed to the sink AFTER this subscriber was subscribed, or elements * that have been buffered due to backpressure/warm up.
  • *
*

* */ ManyWithUpstream multicastOnBackpressureBuffer(); /** * A {@link Sinks.ManyWithUpstream} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: warm up. Remembers up to {@code bufferSize} * elements pushed via {@link Many#tryEmitNext(Object)} before the first {@link Subscriber} is registered.
  • *
  • Backpressure : this sink honors downstream demand by conforming to the lowest demand in case * of multiple subscribers.
    If the difference between multiple subscribers is too high compared to {@code bufferSize}: *
    • {@link Many#tryEmitNext(Object) tryEmitNext} will return {@link EmitResult#FAIL_OVERFLOW}
    • *
    • {@link Many#emitNext(Object, Sinks.EmitFailureHandler) emitNext} will terminate the sink by {@link Many#emitError(Throwable, Sinks.EmitFailureHandler) emitting} * an {@link Exceptions#failWithOverflow() overflow error}.
    *
  • *
  • Replaying: No replay of values seen by earlier subscribers. Only forwards to a {@link Subscriber} * the elements that have been pushed to the sink AFTER this subscriber was subscribed, or elements * that have been buffered due to backpressure/warm up.
  • *
*

* * * @param bufferSize the maximum queue size * @param autoCancel should the sink fully shutdowns (not publishing anymore) when the last subscriber cancels */ ManyWithUpstream multicastOnBackpressureBuffer(int bufferSize, boolean autoCancel); } /** * Provides unicast: 1 sink, 1 {@link Subscriber} */ public interface UnicastSpec { /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Unicast: contrary to most other {@link Sinks.Many}, the * {@link Flux} view rejects {@link Subscriber subscribers} past the first one.
  • *
  • Backpressure : this sink honors downstream demand of its single {@link Subscriber}.
  • *
  • Replaying: non-applicable, since only one {@link Subscriber} can register.
  • *
  • Without {@link Subscriber}: all elements pushed to this sink are remembered and will * be replayed once the {@link Subscriber} subscribes.
  • *
*/ Sinks.Many onBackpressureBuffer(); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Unicast: contrary to most other {@link Sinks.Many}, the * {@link Flux} view rejects {@link Subscriber subscribers} past the first one.
  • *
  • Backpressure : this sink honors downstream demand of its single {@link Subscriber}.
  • *
  • Replaying: non-applicable, since only one {@link Subscriber} can register.
  • *
  • Without {@link Subscriber}: depending on the queue, all elements pushed to this sink are remembered and will * be replayed once the {@link Subscriber} subscribes.
  • *
* * @param queue an arbitrary queue to use that must at least support Single Producer / Single Consumer semantics */ Sinks.Many onBackpressureBuffer(Queue queue); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Unicast: contrary to most other {@link Sinks.Many}, the * {@link Flux} view rejects {@link Subscriber subscribers} past the first one.
  • *
  • Backpressure : this sink honors downstream demand of its single {@link Subscriber}.
  • *
  • Replaying: non-applicable, since only one {@link Subscriber} can register.
  • *
  • Without {@link Subscriber}: depending on the queue, all elements pushed to this sink are remembered and will * be replayed once the {@link Subscriber} subscribes.
  • *
* * @param queue an arbitrary queue to use that must at least support Single Producer / Single Consumer semantics * @param endCallback when a terminal signal is observed: error, complete or cancel */ Sinks.Many onBackpressureBuffer(Queue queue, Disposable endCallback); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Unicast: contrary to most other {@link Sinks.Many}, the * {@link Flux} view rejects {@link Subscriber subscribers} past the first one.
  • *
  • Backpressure : this sink honors downstream demand of the Subscriber, and will emit {@link Subscriber#onError(Throwable)} if there is a mismatch.
  • *
  • Replaying: No replay. Only forwards to a {@link Subscriber} the elements that have been * pushed to the sink AFTER this subscriber was subscribed.
  • *
*/ Sinks.Many onBackpressureError(); } /** * Provides multicast : 1 sink, N {@link Subscriber} */ public interface MulticastSpec { /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: warm up. Remembers up to {@link Queues#SMALL_BUFFER_SIZE} * elements pushed via {@link Many#tryEmitNext(Object)} before the first {@link Subscriber} is registered.
  • *
  • Backpressure : this sink honors downstream demand by conforming to the lowest demand in case * of multiple subscribers.
    If the difference between multiple subscribers is greater than {@link Queues#SMALL_BUFFER_SIZE}: *
    • {@link Many#tryEmitNext(Object) tryEmitNext} will return {@link EmitResult#FAIL_OVERFLOW}
    • *
    • {@link Many#emitNext(Object, Sinks.EmitFailureHandler) emitNext} will terminate the sink by {@link Many#emitError(Throwable, Sinks.EmitFailureHandler) emitting} * an {@link Exceptions#failWithOverflow() overflow error}.
    *
  • *
  • Replaying: No replay of values seen by earlier subscribers. Only forwards to a {@link Subscriber} * the elements that have been pushed to the sink AFTER this subscriber was subscribed, or elements * that have been buffered due to backpressure/warm up.
  • *
*

* */ Sinks.Many onBackpressureBuffer(); /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: warm up. Remembers up to {@code bufferSize} * elements pushed via {@link Many#tryEmitNext(Object)} before the first {@link Subscriber} is registered.
  • *
  • Backpressure : this sink honors downstream demand by conforming to the lowest demand in case * of multiple subscribers.
    If the difference between multiple subscribers is too high compared to {@code bufferSize}: *
    • {@link Many#tryEmitNext(Object) tryEmitNext} will return {@link EmitResult#FAIL_OVERFLOW}
    • *
    • {@link Many#emitNext(Object, Sinks.EmitFailureHandler) emitNext} will terminate the sink by {@link Many#emitError(Throwable, Sinks.EmitFailureHandler) emitting} * an {@link Exceptions#failWithOverflow() overflow error}.
    *
  • *
  • Replaying: No replay of values seen by earlier subscribers. Only forwards to a {@link Subscriber} * the elements that have been pushed to the sink AFTER this subscriber was subscribed, or elements * that have been buffered due to backpressure/warm up.
  • *
*

* * * @param bufferSize the maximum queue size */ Sinks.Many onBackpressureBuffer(int bufferSize); /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: warm up. Remembers up to {@code bufferSize} * elements pushed via {@link Many#tryEmitNext(Object)} before the first {@link Subscriber} is registered.
  • *
  • Backpressure : this sink honors downstream demand by conforming to the lowest demand in case * of multiple subscribers.
    If the difference between multiple subscribers is too high compared to {@code bufferSize}: *
    • {@link Many#tryEmitNext(Object) tryEmitNext} will return {@link EmitResult#FAIL_OVERFLOW}
    • *
    • {@link Many#emitNext(Object, Sinks.EmitFailureHandler) emitNext} will terminate the sink by {@link Many#emitError(Throwable, Sinks.EmitFailureHandler) emitting} * an {@link Exceptions#failWithOverflow() overflow error}.
    *
  • *
  • Replaying: No replay of values seen by earlier subscribers. Only forwards to a {@link Subscriber} * the elements that have been pushed to the sink AFTER this subscriber was subscribed, or elements * that have been buffered due to backpressure/warm up.
  • *
*

* * * @param bufferSize the maximum queue size * @param autoCancel should the sink fully shutdowns (not publishing anymore) when the last subscriber cancels */ Sinks.Many onBackpressureBuffer(int bufferSize, boolean autoCancel); /** A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: fail fast on {@link Many#tryEmitNext(Object) tryEmitNext}.
  • *
  • Backpressure : notify the caller with {@link EmitResult#FAIL_OVERFLOW} if any of the subscribers * cannot process an element, failing fast and backing off from emitting the element at all (all or nothing). * From the perspective of subscribers, data is dropped and never seen but they are not terminated. *
  • *
  • Replaying: No replay of elements. Only forwards to a {@link Subscriber} the elements that * have been pushed to the sink AFTER this subscriber was subscribed, provided all of the subscribers * have demand.
  • *
*

* * * @param the type of elements to emit * @return a multicast {@link Sinks.Many} that "drops" in case any subscriber is too slow */ Sinks.Many directAllOrNothing(); /** A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: fail fast on {@link Many#tryEmitNext(Object) tryEmitNext}.
  • *
  • Backpressure : notify the caller with {@link EmitResult#FAIL_OVERFLOW} if none * of the subscribers can process an element. Otherwise, it ignores slow subscribers and emits the * element to fast ones as a best effort. From the perspective of slow subscribers, data is dropped * and never seen, but they are not terminated. *
  • *
  • Replaying: No replay of elements. Only forwards to a {@link Subscriber} the elements that * have been pushed to the sink AFTER this subscriber was subscribed.
  • *
*

* * * @param the type of elements to emit * @return a multicast {@link Sinks.Many} that "drops" in case of no demand from any subscriber */ Sinks.Many directBestEffort(); } /** * Provides multicast with history/replay capacity : 1 sink, N {@link Subscriber} */ public interface MulticastReplaySpec { /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: all elements pushed to this sink are remembered, * even when there is no subscriber.
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: all elements pushed to this sink are replayed to new subscribers.
  • *
*/ Sinks.Many all(); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: all elements pushed to this sink are remembered, * even when there is no subscriber.
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: all elements pushed to this sink are replayed to new subscribers.
  • *
* @param batchSize the underlying buffer will optimize storage by linked arrays of given size */ Sinks.Many all(int batchSize); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: the latest element pushed to this sink are remembered, * even when there is no subscriber. Older elements are discarded
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: the latest element pushed to this sink is replayed to new subscribers.
  • *
*/ Sinks.Many latest(); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: the latest element pushed to this sink are remembered, * even when there is no subscriber.
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: the latest element pushed to this sink is replayed to new subscribers. If none the default value is replayed
  • *
* * @param value default value if there is no latest element to replay */ Sinks.Many latestOrDefault(T value); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: up to {@code historySize} elements pushed to this sink are remembered, * even when there is no subscriber. Older elements are discarded
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: up to {@code historySize} elements pushed to this sink are replayed to new subscribers. * Older elements are discarded.
  • *
*

* Note that though historySize of zero is forbidden, the desired equivalent effect can usually be achieved * with the {@link Duration} based variant: {@link #limit(Duration) limit(Duration.ZERO)}. * * @param historySize maximum number of elements able to replayed, strictly positive */ Sinks.Many limit(int historySize); /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: all elements pushed to this sink are remembered until their {@code maxAge} is reached, * even when there is no subscriber. Older elements are discarded
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: up to {@code historySize} elements pushed to this sink are replayed to new subscribers. * Older elements are discarded.
  • *
* * @param maxAge maximum retention time for elements to be retained */ Sinks.Many limit(Duration maxAge); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: all elements pushed to this sink are remembered until their {@code maxAge} is reached, * even when there is no subscriber. Older elements are discarded
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: up to {@code historySize} elements pushed to this sink are replayed to new subscribers. * Older elements are discarded.
  • *
* Note: Age is checked when a signal occurs, not using a background task. * * @param maxAge maximum retention time for elements to be retained * @param scheduler a {@link Scheduler} to derive the time from */ Sinks.Many limit(Duration maxAge, Scheduler scheduler); /** * A {@link Sinks.Many} with the following characteristics: *
    *
  • Multicast
  • *
  • Without {@link Subscriber}: up to {@code historySize} elements pushed to this sink are remembered, * until their {@code maxAge} is reached, even when there is no subscriber. Older elements are discarded
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: up to {@code historySize} elements pushed to this sink are replayed to new subscribers. * Older elements are discarded.
  • *
* Note: Age is checked when a signal occurs, not using a background task. *

* Note that though historySize of zero is forbidden, the desired equivalent effect can usually be achieved * by setting the {@code maxAge} to {@link Duration#ZERO}. * * @param historySize maximum number of elements able to replayed, strictly positive * @param maxAge maximum retention time for elements to be retained */ Sinks.Many limit(int historySize, Duration maxAge); /** * A {@link Sinks.Many} with the following characteristics: *

    *
  • Multicast
  • *
  • Without {@link Subscriber}: up to {@code historySize} elements pushed to this sink are remembered, * until their {@code maxAge} is reached, even when there is no subscriber. Older elements are discarded.
  • *
  • Backpressure : this sink honors downstream demand of individual subscribers.
  • *
  • Replaying: up to {@code historySize} elements pushed to this sink are replayed to new subscribers. * Older elements are discarded.
  • *
* Note: Age is checked when a signal occurs, not using a background task. *

* Note that though historySize of zero is forbidden, the desired equivalent effect can usually be achieved * by setting the {@code maxAge} to {@link Duration#ZERO}. * * @param historySize maximum number of elements able to replayed, strictly positive * @param maxAge maximum retention time for elements to be retained * @param scheduler a {@link Scheduler} to derive the time from */ Sinks.Many limit(int historySize, Duration maxAge, Scheduler scheduler); } /** * A base interface for standalone {@link Sinks} with {@link Flux} semantics. *

* The sink can be exposed to consuming code as a {@link Flux} via its {@link #asFlux()} view. * * @author Simon Baslé * @author Stephane Maldini */ public interface Many extends Scannable { /** * Try emitting a non-null element, generating an {@link Subscriber#onNext(Object) onNext} signal. * The result of the attempt is represented as an {@link EmitResult}, which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitNext(Object, EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. *

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, ...). * * @param t the value to emit, not null * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see Subscriber#onNext(Object) */ EmitResult tryEmitNext(T t); /** * Try to terminate the sequence successfully, generating an {@link Subscriber#onComplete() onComplete} * signal. The result of the attempt is represented as an {@link EmitResult}, which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitComplete(EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. * * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see Subscriber#onComplete() */ EmitResult tryEmitComplete(); /** * Try to fail the sequence, generating an {@link Subscriber#onError(Throwable) onError} * signal. The result of the attempt is represented as an {@link EmitResult}, which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitError(Throwable, EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. * * @param error the exception to signal, not null * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see Subscriber#onError(Throwable) */ EmitResult tryEmitError(Throwable error); /** * A simplified attempt at emitting a non-null element via the {@link #tryEmitNext(Object)} API, generating an * {@link Subscriber#onNext(Object) onNext} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitNext(Object)} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitNext(Object)} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: no particular handling. should ideally discard the value but at that * point there's no {@link Subscriber} from which to get a contextual discard handler. *
  • *
  • * {@link EmitResult#FAIL_OVERFLOW}: discard the value ({@link Operators#onDiscard(Object, Context)}) * then call {@link #emitError(Throwable, Sinks.EmitFailureHandler)} with a {@link Exceptions#failWithOverflow(String)} exception. *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: discard the value ({@link Operators#onDiscard(Object, Context)}). *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: drop the value ({@link Operators#onNextDropped(Object, Context)}). *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case for safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param t the value to emit, not null * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitNext(Object) * @see Subscriber#onNext(Object) */ void emitNext(T t, EmitFailureHandler failureHandler); /** * A simplified attempt at completing via the {@link #tryEmitComplete()} API, generating an * {@link Subscriber#onComplete() onComplete} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitComplete()} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitComplete()} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_OVERFLOW}: irrelevant as onComplete is not driven by backpressure. *
  • *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: the completion can be ignored since nobody is listening. * Note that most vanilla reactor sinks never trigger this result for onComplete, replaying the * terminal signal to later subscribers instead (to the exception of {@link UnicastSpec#onBackpressureError()}). *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: the completion can be ignored since nobody is interested. *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: the extra completion is basically ignored since there was a previous * termination signal, but there is nothing interesting to log. *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case in safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitComplete() * @see Subscriber#onComplete() */ void emitComplete(EmitFailureHandler failureHandler); /** * A simplified attempt at failing the sequence via the {@link #tryEmitError(Throwable)} API, generating an * {@link Subscriber#onError(Throwable) onError} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitError(Throwable)} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitError(Throwable)} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_OVERFLOW}: irrelevant as onError is not driven by backpressure. *
  • *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: the error is ignored since nobody is listening. Note that most vanilla reactor sinks * never trigger this result for onError, replaying the terminal signal to later subscribers instead * (to the exception of {@link UnicastSpec#onBackpressureError()}). *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: the error can be ignored since nobody is interested. *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: the error unexpectedly follows another terminal signal, so it is * dropped via {@link Operators#onErrorDropped(Throwable, Context)}. *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case in safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param error the exception to signal, not null * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitError(Throwable) * @see Subscriber#onError(Throwable) */ void emitError(Throwable error, EmitFailureHandler failureHandler); /** * Get how many {@link Subscriber Subscribers} are currently subscribed to the sink. *

* This is a best effort peek at the sink state, and a subsequent attempt at emitting * to the sink might still return {@link EmitResult#FAIL_ZERO_SUBSCRIBER} where relevant. * (generally in {@link #tryEmitNext(Object)}). Request (and lack thereof) isn't taken * into account, all registered subscribers are counted. * * @return the number of subscribers at the time of invocation */ int currentSubscriberCount(); /** * Return a {@link Flux} view of this sink. Every call returns the same instance. * * @return the {@link Flux} view associated to this {@link Sinks.Many} */ Flux asFlux(); } /** * A {@link Sinks.Many} which additionally allows being subscribed to an upstream {@link Publisher}, * which is an advanced pattern requiring external synchronization. See {@link #subscribeTo(Publisher)}} for more details. * * @param the type of data emitted by the sink */ public interface ManyWithUpstream extends Many { /** * Explicitly subscribe this {@link Sinks.Many} to an upstream {@link Publisher} without * exposing it as a {@link Subscriber} at all. *

* Note that when this is done, one MUST stop using emit/tryEmit APIs, reserving signal * creation to be the sole responsibility of the upstream {@link Publisher}. *

* The returned {@link Disposable} provides a way of both unsubscribing from the upstream * and terminating the sink: currently registered subscribers downstream receive an {@link Subscriber#onError(Throwable) onError} * signal with a {@link java.util.concurrent.CancellationException} and further attempts at subscribing * to the sink will trigger a similar signal immediately (in which case the returned {@link Disposable} might be no-op). *

* Any attempt at subscribing the same {@link ManyWithUpstream} multiple times throws an {@link IllegalStateException} * indicating that the subscription must be unique. */ Disposable subscribeTo(Publisher upstream); } /** * A base interface for standalone {@link Sinks} with complete-or-fail semantics. *

* The sink can be exposed to consuming code as a {@link Mono} via its {@link #asMono()} view. * * @param a generic type for the {@link Mono} view, allowing composition * @author Simon Baslé * @author Stephane Maldini */ public interface Empty extends Scannable { /** * Try to complete the {@link Mono} without a value, generating only an {@link Subscriber#onComplete() onComplete} signal. * The result of the attempt is represented as an {@link EmitResult}, which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitEmpty(EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. * * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see #emitEmpty(Sinks.EmitFailureHandler) * @see Subscriber#onComplete() */ EmitResult tryEmitEmpty(); /** * Try to fail the {@link Mono}, generating only an {@link Subscriber#onError(Throwable) onError} signal. * The result of the attempt is represented as an {@link EmitResult}, which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitError(Throwable, EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. * * @param error the exception to signal, not null * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see #emitError(Throwable, Sinks.EmitFailureHandler) * @see Subscriber#onError(Throwable) */ EmitResult tryEmitError(Throwable error); /** * A simplified attempt at completing via the {@link #tryEmitEmpty()} API, generating an * {@link Subscriber#onComplete() onComplete} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitEmpty()} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitEmpty()} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_OVERFLOW}: irrelevant as onComplete is not driven by backpressure. *
  • *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: the completion can be ignored since nobody is listening. * Note that most vanilla reactor sinks never trigger this result for onComplete, replaying the * terminal signal to later subscribers instead (to the exception of {@link UnicastSpec#onBackpressureError()}). *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: the completion can be ignored since nobody is interested. *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: the extra completion is basically ignored since there was a previous * termination signal, but there is nothing interesting to log. *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case in safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitEmpty() * @see Subscriber#onComplete() */ void emitEmpty(EmitFailureHandler failureHandler); /** * A simplified attempt at failing the sequence via the {@link #tryEmitError(Throwable)} API, generating an * {@link Subscriber#onError(Throwable) onError} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitError(Throwable)} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitError(Throwable)} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_OVERFLOW}: irrelevant as onError is not driven by backpressure. *
  • *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: the error is ignored since nobody is listening. Note that most vanilla reactor sinks * never trigger this result for onError, replaying the terminal signal to later subscribers instead * (to the exception of {@link UnicastSpec#onBackpressureError()}). *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: the error can be ignored since nobody is interested. *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: the error unexpectedly follows another terminal signal, so it is * dropped via {@link Operators#onErrorDropped(Throwable, Context)}. *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case in safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param error the exception to signal, not null * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitError(Throwable) * @see Subscriber#onError(Throwable) */ void emitError(Throwable error, EmitFailureHandler failureHandler); /** * Get how many {@link Subscriber Subscribers} are currently subscribed to the sink. *

* This is a best effort peek at the sink state, and a subsequent attempt at emitting * to the sink might still return {@link EmitResult#FAIL_ZERO_SUBSCRIBER} where relevant. * Request (and lack thereof) isn't taken into account, all registered subscribers are counted. * * @return the number of active subscribers at the time of invocation */ int currentSubscriberCount(); /** * Return a {@link Mono} view of this sink. Every call returns the same instance. * * @return the {@link Mono} view associated to this {@link Sinks.One} */ Mono asMono(); } /** * A base interface for standalone {@link Sinks} with {@link Mono} semantics. *

* The sink can be exposed to consuming code as a {@link Mono} via its {@link #asMono()} view. * * @author Simon Baslé * @author Stephane Maldini */ public interface One extends Empty { /** * Try to complete the {@link Mono} with an element, generating an {@link Subscriber#onNext(Object) onNext} signal * immediately followed by an {@link Subscriber#onComplete() onComplete} signal. A {@code null} value * will only trigger the onComplete. The result of the attempt is represented as an {@link EmitResult}, * which possibly indicates error cases. *

* See the list of failure {@link EmitResult} in {@link #emitValue(Object, EmitFailureHandler)} javadoc for an * example of how each of these can be dealt with, to decide if the emit API would be a good enough fit instead. *

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, ...). * * @param value the value to emit and complete with, or {@code null} to only trigger an onComplete * @return an {@link EmitResult}, which should be checked to distinguish different possible failures * @see #emitValue(Object, Sinks.EmitFailureHandler) * @see Subscriber#onNext(Object) * @see Subscriber#onComplete() */ EmitResult tryEmitValue(@Nullable T value); /** * A simplified attempt at emitting a non-null element via the {@link #tryEmitValue(Object)} API, generating an * {@link Subscriber#onNext(Object) onNext} signal immediately followed by an {@link Subscriber#onComplete()} signal. * If the result of the attempt is not a {@link EmitResult#isSuccess() success}, implementations SHOULD retry the * {@link #tryEmitValue(Object)} call IF the provided {@link EmitFailureHandler} returns {@code true}. * Otherwise, failures are dealt with in a predefined way that might depend on the actual sink implementation * (see below for the vanilla reactor-core behavior). *

* Generally, {@link #tryEmitValue(Object)} is preferable since it allows a custom handling * of error cases, although this implies checking the returned {@link EmitResult} and correctly * acting on it. This API is intended as a good default for convenience. *

* When the {@link EmitResult} is not a success, vanilla reactor-core operators have the following behavior: *

    *
  • * {@link EmitResult#FAIL_ZERO_SUBSCRIBER}: no particular handling. should ideally discard the value but at that * point there's no {@link Subscriber} from which to get a contextual discard handler. *
  • *
  • * {@link EmitResult#FAIL_OVERFLOW}: discard the value ({@link Operators#onDiscard(Object, Context)}) * then call {@link #emitError(Throwable, Sinks.EmitFailureHandler)} with a {@link Exceptions#failWithOverflow(String)} exception. *
  • *
  • * {@link EmitResult#FAIL_CANCELLED}: discard the value ({@link Operators#onDiscard(Object, Context)}). *
  • *
  • * {@link EmitResult#FAIL_TERMINATED}: drop the value ({@link Operators#onNextDropped(Object, Context)}). *
  • *
  • * {@link EmitResult#FAIL_NON_SERIALIZED}: throw an {@link EmissionException} mentioning RS spec rule 1.3. * Note that {@link Sinks#unsafe()} never trigger this result. It would be possible for an {@link EmitFailureHandler} * to busy-loop and optimistically wait for the contention to disappear to avoid this case for safe sinks... *
  • *
*

* Might throw an unchecked exception as a last resort (eg. in case of a fatal error downstream which cannot * be propagated to any asynchronous handler, a bubbling exception, a {@link EmitResult#FAIL_NON_SERIALIZED} * as described above, ...). * * @param value the value to emit and complete with, a {@code null} is actually acceptable to only trigger an onComplete * @param failureHandler the failure handler that allows retrying failed {@link EmitResult}. * @throws EmissionException on non-serialized access * @see #tryEmitValue(Object) * @see Subscriber#onNext(Object) * @see Subscriber#onComplete() */ void emitValue(@Nullable T value, EmitFailureHandler failureHandler); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy