World
: This is the container abstraction within which actors live and operate. A World
can have a number of Stage
instances in which the life cycles of a subset of live actors are managed. When the World
is started, actors can be created. When the World
terminates, all Stage
and Actor
instances are terminated/stopped.Stage
: Every World
has at least one Stage
, known as the default. The Stage
is specifically where actors are managed and within which they play or execute. There may be multiple Stage
instances, each with several or many actors (even millions) under its management. Each Stage
has an internal Directory
within which live actors are held, and through which they can be found.Actor
: Each actor is an object, but one that reacts to incoming asynchronous messages, and that sends outgoing messages asynchronously. Each actor is assigned a Mailbox
, and a Mailbox
delivers messages though a Dispatcher
. When the actor receives a message, it performs some business behavior internally, and then completes that specific message-handling context. All actors are type safe in that their behaviors are defined by Java method signatures rather than arbitrary object types. Every actor may implement any (practical) number of behavioral interfaces, known as actor protocols.Supervisor
: A recent account of cascading failure describes tens of thousands of nodes lost during a Kafka failure that caused a Kubernetes cluster to self destruct, taking out an entire infrastructure. Using supervision as bulkheads can save your system from catastrophic failure. Actors are supervised in order to deal with failure. When an actor experiences an exception while handling a message, the exception is caught by the message dispatcher and is relayed to the actor’s supervisor as a message. When received by the supervisor, the exceptional message is interpreted to determine the appropriate step to correct the actor’s problem. The corrective action can be one of the following: resume, restart, stop, or escalate. In the case of supervision escalation, the exceptional message is relayed to this supervisor’s supervisor, for it to take some action. There are four kinds of supervision: direct parent, default public root, override of public root, and registered common supervisors for specific actor protocols (behavioral interfaces).Scheduler
: Each Stage
has a scheduler that can be used to schedule future tasks, and that may be repeated on time intervals. An actor determines the timeframe that is needed, and each occasion on which the interval is reached, the actor receives an interval signal message indicating that it is time to perform some task. The receiving actor can then execute some necessary behavior in response to the interval signal. The actor that creates the scheduled task need not be the target actor of the interval signal message.Logger
: Logging capabilities are provided to every actor, and different loggers may be assigned to different actors. Log output occurs asynchronously because loggers are run as actors.Stage
notice that there are three special actors, one that is {bright yellow} with a #, one that is {bright yellow} with a *, and one that is {red} with an X. Respectively, these are:private root actor
, which is the parent of the public root actor and the dead letters actorpublic root actor,
which is the default parent and supervisor if no others are specifieddead letters actor
, which receives actor messages that could not be deliveredProposal
protocol is used. It is unimportant exactly what behavior the Proposal
supports, but you can imagine some sort of description that serves to propose something, such as a job or an expensive product purchase. Further, let's say that the actor that implements the Proposal
protocol is named ProposalActor
.Proposal
as an actor through the World
or a Stage
, their are two parts that are created. One part is an instantiation of the ProposalActor
itself. The created second part is a proxy instance, which also implements the Proposal
protocol. When the answer from the actor creation is given to the client, it is the Proposal
that is backed by the proxy implementation. In other words, in the above code, the proxy is the Proposal proposal
instance returned from World#actorFor()
. Internally the Proposal
proxy knows how to send messages asynchronously to the ProposalActor
instance. The ProposalActor
exists in memory, and any component that has its Proposal
proxy instance may send asynchronous messages to it.Proposal
proxy, never directly on the ProposalActor
java.util.function.Consumer
that holds the intention to invoke the actual method with any parameters on the ProposalActor
instanceConsumer
is wrapped in a io.vlingo.xoom.actors.Message
, which when sent within the local JVM, is implemented by LocalMessage
of the same packageMessage
containing the Consumer
is queued to the actor's Mailbox
, which causes the scheduling of the message for deliveryMessage
is queued in the actor's Mailbox
, the proxy invocation returns to the clientMessage
is polled from the Mailbox
and dispatched to the ProposalActor
Proposal
protocol, the following describes how proxy classes are created.Proposal
using actorFor(protocol, actorType[, args...])
, internally the XOOM Actors queries for a class named Proposal__Proxy
Proposal__Proxy.java
, compiles it, and loads it into its private class loaderStage
can now create instances of the Proposal__Proxy
actorFor(protocol, actorType[, args...])
is used, XOOM Actors actually returns a new instance of Proposal__Proxy
which implements Proposal
totalNodes / 2 + 1
) that can form a healthy cluster. Choosing an even number of nodes works, but in that case, when loosing one node, it doesn’t improve the quorum determination, nor does it strengthen the cluster when all nodes are available.op
or operations port
and app
or application port
.name
, any supported simple datatype
such as String
, Boolean
, Integer
, Double
, etc., and a value
.