Completes<T>
interface defines the means to receive and react to the results from an asynchronous operation at some time in the future. Using the word "future" may be a giveaway to this tool, because in various languages and toolkits this concept is known as Future<T>
. We purposely avoided the use of "future" terminology, because the preexisting components work inconsistently and also house some complex naming and behavior that we, of course, simplified. Here is how to put Completes<T>
to good use.Actor
asynchronously. Because the delivery to the underlying Actor
that implements the Calculator
protocol behaviors is asynchronous, there is no way for the result of the behavior to be known immediately. The contract to the client is a result that expresses the intention to later provide an Integer
result. The eventual answer of type Integer
is a parameter to Completes
. After the message factorialOf(n)
has been received by the Actor
and the calculation has completed, the Actor
answers the result, which is also delivered asynchronously. Eventually the internals of the Completes<T>
implementation sees the calculated result, at which time it hands the result to any functions that have been registered by the client with the Completes<T>
.Completes<T>
internals, the client is given the opportunity to do something with the value. In this case the client simply prints the result. This can be expressed in a more condensed fashion.andThenConsume(c)
is a means to register a Consumer<Integer>
that does not produce a return value. There are other means to register functions, and the majority are concerned mostly with pipelining results from one kind of filter to another.andThen(f)
registers a Function<T,R>
that will be applied synchronously when the factorial is available. The factorial result is the T
parameter and the R
return value becomes the result of andThen(f)
. This result, which is the square of the original factorial calculation, becomes the input to the andThenTo(f)
. Notice the difference in naming. The andThen(f)
is synchronous, but the andThenTo(f)
handles an asynchronous result. This is used to pass the squared outcome of andThen(f)
to the calculator to determine the factorial of the "factorial of 42 and then squared"-value. In other words, the andThenTo(f)
is expecting you to send a message to an actor that will produce another eventual result. The Actor
and protocol used could be any one, it's just that here the Calculator
protocol and implementing Actor
was reused.andThen()
. The exact same optional and required parameters are available to andThenTo()
.andThen(f)
as well as andThenTo(f)
support the same parameters. However, the andThen(f)
requires a return value of Completes<T>
, while andThenTo(f)
allows returning a different type that is parameterized by the client sender.otherwiseConsume()
is invoked rather than the function that is registered with andThenTo()
.otherwise(failedValue)
and otherwiseConsume(failedValue)
are available. If you provide a timeout
threshold but not a failedValue
, the failedValue
defaults to null
.Actor
may answer the failedValue
as a result of its behavior, which will also cause the otherwise(failedValue)
to be invoked. Thus, it is not only a timeout that can possibly cause the otherwise()
handler to be invoked.Completes<T>
facilities take a look at the interface definition found in the xoom-common
project (repository), in io.vlingo.xoom.common.Completes
.Completes<T>
results inside an Actor
. When the function of theandThen(f)
or other andThen???(f)
is applied, the thread is not one assigned to the Actor
for receiving a message. Rather, the thread is one assigned to a background Actor
specifically designated to deliver the Completes<T>
results to the andThen()
function. Thus, it is quite possible/likely that the function is applied at the same time that the enclosing Actor
is handling a message delivery via its mailbox for an implemented protocol. If both threads simultaneously modify the state of the Actor
there will be races on state access and mutation. This will inevitably cause data corruption.Actor
must consume a Completes<T>
results, you should self-send that result to a protocol designed for this purpose. For example,Actor
requesting reserveTravel()
is the BookingActor
that implements the Booking
protocol. Inside andThenTo()
the function sends record(reservation)
to the Booking
, which will eventually be received by the enclosing BookingActor
. The BookingActor
will thus receive thisrecord(reservation)
message through its mailbox on a thread that has exclusive access to its state to effect the reservation recording.recoverFrom()
. Consider this example:recoverFrom()
is used to report the cause of the exceptional problem to a component that can handle to problem using an alternate workflow.Outcome
is a result of an operation that may be either successful or a failure. If the resulting Outcome
is a success then the client may respond in a positive manner, and if a failure in a recovery or compensating manner. Thus, there are two concrete types available, Success
and Failure
.Outcome<StorageException, Result>
Outcome
producer may provide one or the other, but not both. If successful, the behavior would produce something such as the following.Success.of(Result.Success)
Exception
value of e
, the following may be the product of the component.Failure.of(new StorageException(Result.Failure, e.getMessage(), e))
Outcome
will have one value or the other, either StorageException
or Result
. How is it determined by the client and reacted to?Complete<T>
API. When the operation is successful the andThen(f)
operation is executed. When the operation is a failure the otherwise(f)
operation is executed, with the Exception
cause as the parameter. The otherwise(f)
is not required to throw an Exception
, but may answer the same or different Result
value that is found in the cause
.Stage
has its own Scheduler
, which may be used to produce time-lapsed events that are sent to an Actor
.Actor
can schedule itself or another Actor
, such as one or more of its children, for some timed event notification. In other words, it need not pass itself as the Scheduled
instance.100
milliseconds of the registration and will repeat every 1
second (1_000
milliseconds). The Actor scheduling itself for notifications must implement the Scheduled
protocol, and it passes an Actor
enabled reference to that effect using the runtime method selfAs()
. The Actor
can associate some specific data with which it will be notified on each event, which in this example is the DataPacket
instance packet
. This DataPacket
type is only used for the example, and would be replaced with your own type, or you can pass null
if the data is unused.Scheduled
object you are provided a Cancellable
instance. You may use this instance to cancel one-time or repeating occurrences.Actor
receiving the timed event will be notified using the intervalSignal()
method of the Scheduled
protocol.JsonSerialization
. Internally this utility uses the com.google.gson.Gson
serializer, which supports field-level access rather than requiring JavaBean accessor methods. The following operations are available.Object
parameter to a String
:List<T>
parameter to a String
:serialization
parameter to an instance of Class<T>
:serialization
parameter to an instance of Type
:serialization
parameter to an instance of a List
of type Type
:void
and the single value type, respectively, to represent those tuples. Using a tuple type eliminates the need to create many tiny types just to shuttle around individual values of which it is unimportant to give a domain-specific type.Tuple2
, Tuple3
, and Tuple4
. Each of these tuple types support the specific number of values indicated by the trailing number of the name.Tuple2
, use class method from()
as follows:Tuple3
and Tuple4
, you may use the following:1
, a minor version of 7
, and a patch version of 3
:major
version may have a maximum value of 32_767
, and the minor
and patch
values are limited to 255
each. The minimum value of all parts is 0
.SemanticVersion
utility tool, the representations supported are both packed integer and text format. These are the available operations.SemanticVersion
instance with the given major
, minor
, and patch
values:SemanticVersion
instance with the given major
, minor
, and patch
values as represented by the version
parameter. The version
parameter must have the representation "x.y.z"
, where x
, y
, and z
, are numbers:String
representation of the semantic version represented by the packed version integer value:major
, minor
, and patch
parameter values:major
, minor
, and patch
values as represented by the version
parameter. The version
parameter must have the representation "x.y.z"
, where x
, y
, and z
, are numbers:SemanticVersion
instances provide the following behaviors.true
if the receiver SemanticVersion
is compatible with the previous SemanticVersion
parameter:major
version of the receiver is one greater than the previous major
version, and all other values are the same
(b) the minor
version of the receiver is one greater than the previous minor
version, and all other values are the same
(c) the patch
version of the receiver is one greater than the previous patch
version, and all other values are the same.SemanticVersion
with its major
version one greater than the receiver's, and all other values the same:SemanticVersion
with its minor
version one greater than the receiver's, and all other values the same:SemanticVersion
with its patch
version one greater than the receiver's, and all other values the same:String
representation: