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

io.vlingo.common.Completes Maven / Gradle / Ivy

There is a newer version: 1.7.5
Show newest version
// Copyright © 2012-2020 VLINGO LABS. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.

package io.vlingo.common;

import java.util.function.Consumer;
import java.util.function.Function;

import io.vlingo.common.completes.SinkAndSourceBasedCompletes;
import io.vlingo.common.completes.exceptions.FailedOperationException;

/**
 * {@code Completes} models the eventual completion of an asynchronous operation
 * that has an answer (return value) of a specific type. You will find this
 * similar to {@code Future} and {@code CompletableFuture} from the Java platform. Yet,
 * {@code Completes} is designed for non-blocking and is typically used in
 * that manner. There is a means to explicitly block on the outcome but
 * this is used only for testing.
 *
 * 

* Use {@code Completes} beyond handling the eventual outcome of asynchronous outcomes. * For example, use a pipeline of multiple {@code Completes} when you must send a number * of asynchronous messages for multiple outcomes, but each outcome must precede the next. * Thus, while each message send is entirely asynchronous, {@code Completes} manages the * sequencing of each message and its outcome with the possibility of each outcome being used * for the next message send. {@code Completes} is a monad. * * * reservations * .reserveTravel(ticketingDetails) * .andThenTo(reservation -> booking.record(reservation)) * .andThenTo(bookingRecord -> traveler.bookFor(bookingRecord)) * .andThenTo(points -> rewards.credit(points)); * * *

* Note that the various forms of {@code andThenTo()} pipeline using a nested {@code Completes} * instance, making it possible for the registered {@code Function} to send an asynchronous * message to an actor with without damaging the parent {@code Completes}. Using {@code andThen()} * to send an asynchronous message to an actor will have undefined results. * * Note that the {@code Completes} doesn't necessarily need to be executed when there is an outcome * if there is no subscription to it. Deciding when to run is implementation dependent, and is encouraged * to subscribe to the {@code Completes} using the {@code andFinallyConsume} method. * * @param the type that is expected as the outcome (return value) */ public interface Completes { /** * Answer a new {@code Completes} that uses the {@code scheduler}. The * instance has not completed at the time of creation. * @param scheduler the Scheduler to use for timeouts * @param the T typed outcome of the Completes * @return {@code Completes} */ static Completes using(final Scheduler scheduler) { if (SinkAndSourceBasedCompletes.isToggleActive()) { return SinkAndSourceBasedCompletes.withScheduler(scheduler); } return new BasicCompletes(scheduler); } static Completes noTimeout() { return new BasicCompletes((Scheduler) null); } /** * Answer a new {@code Completes} that has a successful {@code outcome}. * The instance has already completed at the time of creation, * which means that any function/accessor used to read the * successful {@code outcome} will be immediate. * @param outcome the T typed outcome answer (return value) * @param the T typed outcome of the Completes * @return {@code Completes} */ static Completes withSuccess(final T outcome) { if (SinkAndSourceBasedCompletes.isToggleActive()) { return SinkAndSourceBasedCompletes.withScheduler(new Scheduler()).with(outcome); } return new BasicCompletes(outcome, true); } /** * Answer a new {@code Completes} that has a failure {@code outcome}. * The instance has already completed at the time of creation, * which means that any function/accessor used to read the * failure {@code outcome} will be immediate. * @param outcome the T typed outcome answer (return value) * @param the T typed outcome of the Completes * @return {@code Completes} */ static Completes withFailure(final T outcome) { if (SinkAndSourceBasedCompletes.isToggleActive()) { SinkAndSourceBasedCompletes completes = SinkAndSourceBasedCompletes .withScheduler(new Scheduler()); completes.source.emitError(new FailedOperationException(outcome)); return completes; } return new BasicCompletes(outcome, false); } /** * Answer a new {@code Completes} that has a failure outcome of {@code null}. * The instance has already completed at the time of creation, * which means that any function/accessor used to read the * failure {@code outcome} will be immediate. * @param the T typed outcome of the Completes * @return {@code Completes} */ static Completes withFailure() { return withFailure(null); } /** * Answer a new {@code Completes} that is repeatable, meaning that * following a given completion the instance may be reused to * achieve one or more subsequent eventual outcomes. To do so * use {@link Completes#repeat()} to prepare for the next outcome. * The instance has not completed at the time of creation. * @param scheduler the Scheduler to use for timeouts * @param the T typed outcome of the Completes * @see Completes#repeat() * @return {@code Completes} */ static Completes repeatableUsing(final Scheduler scheduler) { if (SinkAndSourceBasedCompletes.isToggleActive()) { return SinkAndSourceBasedCompletes.withScheduler(scheduler); } return new RepeatableCompletes(scheduler); } /** * Answer a new {@code Completes} that is repeatable, meaning that * following a given completion the instance may be reused to * achieve one or more subsequent eventual outcomes. To do so * use {@link Completes#repeat()} to prepare for the next outcome. * The instance has already completed successfully at the time of creation. * @param outcome the T typed outcome answer (return value) of {@code null} * @param the T typed outcome of the Completes * @see Completes#repeat() * @return {@code Completes} */ static Completes repeatableWithSuccess(final T outcome) { if (SinkAndSourceBasedCompletes.isToggleActive()) { return SinkAndSourceBasedCompletes.withScheduler(new Scheduler()).with(outcome); } return new RepeatableCompletes(outcome, true); } /** * Answer a new {@code Completes} that is repeatable, meaning that * following a given completion the instance may be reused to * achieve one or more subsequent eventual outcomes. To do so * use {@link Completes#repeat()} to prepare for the next outcome. * The instance has already completed with failure at the time of creation. * @param outcome the T typed outcome answer (return value) of {@code null} * @param the T typed outcome of the Completes * @see Completes#repeat() * @return {@code Completes} */ static Completes repeatableWithFailure(final T outcome) { if (SinkAndSourceBasedCompletes.isToggleActive()) { Completes failure = SinkAndSourceBasedCompletes.withScheduler(new Scheduler()).with(outcome); failure.failed(); return failure; } return new RepeatableCompletes(outcome, false); } /** * Answer a new {@code Completes} that is repeatable, meaning that * following a given completion the instance may be reused to * achieve one or more subsequent eventual outcomes. To do so * use {@link Completes#repeat()} to prepare for the next outcome. * The instance has already completed with failure of {@code null} at the * time of creation. * @param the T typed outcome of the Completes * @see Completes#repeat() * @return {@code Completes} */ static Completes repeatableWithFailure() { return repeatableWithFailure(null); } /** * Answer the {@code Completes} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available, along with the {@code timeout} and * {@code failedOutcomeValue}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that you must not use any form of {@code andThen()} to send a message to an actor. See * {@link Completes#andThenTo(long, Object, Function)} for that. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param failedOutcomeValue the O typed value answered in the case of failure, including for timeout * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @param the O typed outcome of the Completes, which may be different from T * @return {@code Completes} */ Completes andThen(final long timeout, final O failedOutcomeValue, final Function function); /** * Answer the {@code Completes} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available, along with the {@code failedOutcomeValue}. * There is no timeout specified in this operation, meaning that the outcome could be * infinite. Note that failure is different from exceptional outcomes, which are handled by * {@link Completes#recoverFrom(Function)}. *

* Note that you must not use any form of {@code andThen()} to send a message to an actor. See * {@link Completes#andThenTo(Object, Function)} for that. * @param failedOutcomeValue the O typed value answered in the case of failure * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @param the O typed outcome of the Completes, which may be different from T * @return {@code Completes} */ Completes andThen(final O failedOutcomeValue, final Function function); /** * Answer the {@code Completes} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available, along with the {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that you must not use any form of {@code andThen()} to send a message to an actor. See * {@link Completes#andThenTo(long, Function)} for that. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @param the O typed outcome of the Completes, which may be different from T * @return {@code Completes} */ Completes andThen(final long timeout, final Function function); /** * Answer the {@code Completes} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available. There is no {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that you must not use any form of {@code andThen()} to send a message to an actor. See * {@link Completes#andThenTo(Function)} for that. * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @param the O typed outcome of the Completes, which may be different from T * @return {@code Completes} */ Completes andThen(final Function function); /** * Answer the {@code Completes} instance after registering the {@code consumer} to be used to * accept the value of type {@code T} when it is available, along with the {@code timeout} and * {@code failedOutcomeValue}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param failedOutcomeValue the T typed value answered in the case of failure, including for timeout * @param consumer the {@code Consumer} to receive the {@code Completes} of the async operation * @return {@code Completes} */ Completes andThenConsume(final long timeout, final T failedOutcomeValue, final Consumer consumer); /** * Answer the {@code Completes} instance after registering the {@code consumer} to be used to * accept the value of type {@code T} when it is available, along with the {@code failedOutcomeValue}. * There is no timeout specified in this operation, meaning that the outcome could be * infinite. Note that failure is different from exceptional outcomes, which are handled by * {@link Completes#recoverFrom(Function)}. * @param failedOutcomeValue the T typed value answered in the case of failure * @param consumer the {@code Consumer} to receive the {@code Completes} of the async operation * @return {@code Completes} */ Completes andThenConsume(final T failedOutcomeValue, final Consumer consumer); /** * Answer the {@code Completes} instance after registering the {@code consumer} to be used to * accept the value of type {@code T} when it is available, along with the {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param consumer the {@code Consumer} to receive the {@code Completes} of the async operation * @return {@code Completes} */ Completes andThenConsume(final long timeout, final Consumer consumer); /** * Answer the {@code Completes} instance after registering the {@code consumer} to be used to * accept the value of type {@code T} when it is available. There is no {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. * @param consumer the {@code Consumer} to receive the {@code Completes} of the async operation * @return {@code Completes} */ Completes andThenConsume(final Consumer consumer); /** * Answer the {@code O} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available, along with the {@code timeout} and * {@code failedOutcomeValue}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that {@code andThenTo()} pipelines using a nested {@code Completes} instance, making it possible * for the registered {@code Function} to send an asynchronous message to an actor with without damaging * the parent {@code Completes}. Using {@code andThen()} to send an asynchronous message to an actor will * have undefined results. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param failedOutcomeValue the F typed value answered in the case of failure, including for timeout * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code O} outcome * @param the F type of the failedOutcomeValue * @param the O typed outcome, which may be different from T and may be a Completes * @return O */ O andThenTo(final long timeout, final F failedOutcomeValue, final Function function); /** * Answer the {@code O} instance after registering the {@code function} to be used to * apply the value of type {@code T} when it is available, along with the {@code failedOutcomeValue}. * There is no timeout specified in this operation, meaning that the outcome could be * infinite. Note that failure is different from exceptional outcomes, which are handled by * {@link Completes#recoverFrom(Function)}. *

* Note that {@code andThenTo()} pipelines using a nested {@code Completes} instance, making it possible * for the registered {@code Function} to send an asynchronous message to an actor with without damaging * the parent {@code Completes}. Using {@code andThen()} to send an asynchronous message to an actor will * have undefined results. * @param failedOutcomeValue the F typed value answered in the case of failure * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code O} outcome * @param the F type of the failedOutcomeValue * @param the O typed outcome, which may be different from T and may be a Completes * @return O */ O andThenTo(final F failedOutcomeValue, final Function function); /** * Answer the {@code O} instance after registering the {@code function} to be used to * apply the value of type {@code T} when it is available, along with the {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that {@code andThenTo()} pipelines using a nested {@code Completes} instance, making it possible * for the registered {@code Function} to send an asynchronous message to an actor with without damaging * the parent {@code Completes}. Using {@code andThen()} to send an asynchronous message to an actor will * have undefined results. * @param timeout the long number of milliseconds until this {@code Completes} is considered timed out * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code O} outcome * @param the O typed outcome, which may be different from T and may be a Completes * @return O */ O andThenTo(final long timeout, final Function function); /** * Answer the {@code O} instance after registering the {@code function} to be used to * apply the value of type {@code O} when it is available. There is no {@code timeout} and a * failed outcome value of {@code null}. Note that failure is different from exceptional outcomes, * which are handled by {@link Completes#recoverFrom(Function)}. *

* Note that {@code andThenTo()} pipelines using a nested {@code Completes} instance, making it possible * for the registered {@code Function} to send an asynchronous message to an actor with without damaging * the parent {@code Completes}. Using {@code andThen()} to send an asynchronous message to an actor will * have undefined results. * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the O of the next operation * @param the O typed outcome, which may be different from T and may be a Completes * @return O */ O andThenTo(final Function function); /** * Answer the {@code Completes} after registering the {@code function} to be used to * apply the failure outcome if such occurs. * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @return {@code Completes} */ Completes otherwise(final Function function); /** * Answer the {@code Completes} after registering the {@code consumer} to be used to * accept the failure outcome if such occurs. * @param consumer the {@code Consumer} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @return {@code Completes} */ Completes otherwiseConsume(final Consumer consumer); /** * Answer the {@code Completes} after registering the {@code function} to be used to * apply the exceptional outcome if such occurs. * @param function the {@code Function} to receive the {@code Completes} of the async operation and to produce the {@code Completes} of the next operation * @return {@code Completes} */ Completes recoverFrom(final Function function); /** * Answer the {@code O} outcome as the final implicit function in a pipeline. * Subscribes to the current {@code Completes} and runs if the outcome is successful. *

* Note that you must have either {@code andFinally()} or {@code andFinallyConsume()} as * a terminator for your pipeline, or the {@code Completes} will never run. * * @param the O type of outcome from the function * @return {@code Completes} */ Completes andFinally(); /** * Answer the {@code O} outcome as the final function in a pipeline. * Subscribes to the current {@code Completes} and runs if the outcome is successful. *

* Note that you must have either {@code andFinally()} or {@code andFinallyConsume()} as * a terminator for your pipeline, or the {@code Completes} will never run. * * @param function the {@code Function} that will receive the successful value, if any. * @param the O type of outcome from the function * @return {@code Completes} */ Completes andFinally(final Function function); /** * Subscribes to the current {@code Completes} and runs if the outcome is successful. *

* Note that you must have either {@code andFinally()} or {@code andFinallyConsume()} as * a terminator for your pipeline, or the {@code Completes} will never run. * * @param consumer the {@code Consumer} that will receive the successful value, if any. */ void andFinallyConsume(final Consumer consumer); /** * Answer the {@code O} outcome after blocking indefinitely for completion. * @param the O type of outcome * @return O */ O await(); /** * Answer the {@code O} outcome after blocking for a maximum of * {@code timeout} milliseconds for completion. * @param timeout the long maximum number of milliseconds to block for an outcome * @param the O type of outcome * @return O */ O await(final long timeout); /** * Answer whether or not this {@code Completes} has completed. * @return boolean */ boolean isCompleted(); /** * Answer whether or not this {@code Completes} has failed. * @return boolean */ boolean hasFailed(); /** * Cause this {@code Completes} to fail, unless it has already completed. */ void failed(); /** * Answer whether or not this {@code Completes} has an available outcome, * which will be true for either success or failure. * @return boolean */ boolean hasOutcome(); /** * Answer my {@code outcome}, which may be a unknown, success, or failure. * @return T */ T outcome(); /** * Answer myself after I am prepared to handle the next outcome. By default * this throws {@code UnsupportedOperationException}, but will provided intended * behavior and answer if the underlying type is {@code RepeatableCompletes}. Use * {@link Completes#repeatableUsing(Scheduler)} to create a valid instance. * @return {@code Completes} */ Completes repeat(); /** * Answer myself after setting my {@code outcome}. This should normally be used only * by internal operations or when available through an actor for its results. * @param outcome the O typed outcome to set as my outcome * @param the type to be answered * @return {@code Completes} */ Completes with(final O outcome); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy