DomainEvent
will trigger the process to start. The process will then emit a Command
, which is to cause the next step in the process. When the DomainEvent
from that step outcome is seen, process will again emit a Command
, which is to cause the next step in the process. This repeats until the process has completed (if in fact it is meant to complete). The process tracks the current state of the state machine, which along with the next DomainEvent
it sees, will determine the next step to be taken.DomainEvent
is seen by the process as a stimulus, and the process then emits a Command
to cause the next action. This pattern repeats until completion is reached on the far right.Process
standard implementors that are abstract base types. These base classes are meant to be extended by concrete implementors.SourcedProcess
ObjectProcess
StatefulProcess
Process
, the SourcedProcess
is generally the best choice. The use of Command
and/or DomainEvent
types to direct the steps of the process are a natural fit. You may still, however, accomplish the same by using Command
and/or DomainEvent
types within an ObjectProcess
and StatefulProcess
. It may be more a matter of whether you prefer to always persist state snapshots, which you must always do with these two process types.Chronicle<T> chronicle()
Chronicle<S>
, where S
is the type of the state. Since a Process
is a state machine, the current state held by the Chronicle<S>
is the state of the state machine.Process
may be CommandSourced
or EventSourced
, or a combination of both, it could well be that there is no need to use the Chronicle<S>
for full-state persistence. In such cases the Process may require minimal state transitions, and thus any state-representing stream may not be large enough to justify the use of snapshots.transitionTo()
to create a new Chronicle<S>
that wraps the new state of the state machine.Chronicle<S>
to manage your more fine-grained state transitions.String id()
Process
, which should likely be the id()
or streamName()
of the underlying base types: SourcedProcess
, ObjectProcess
, StatefulProcess
.void process(Command command)
Command
inside a ProcessMessage
and persists it to the underlying storage, and then sends it through the configured message exchange.<R> Completes<R> process(Command command, Supplier<R> andThen)
process(Command)
, and also returns the Completes<R>
that provides the eventual outcome of the Supplier<R>
parameter andThen
. After the Command
is safely persisted, the andThen
is executed and its value is given as outcome of the Completes<R>
.void process(DomainEvent event)
DomainEvent
inside a ProcessMessage
and persists it to the underlying storage, and then sends it through the configured message exchange.<R> Completes<R> process(DomainEvent event, Supplier<R> andThen)
process(DomainEvent)
, and also returns the Completes<R>
that provides the eventual outcome of the Supplier<R>
parameter andThen
. After the DomainEvent
is safely persisted, the andThen
is executed and its value is given as outcome of the Completes<R>
.<C> void processAll(List<Source<C>> sources)
Source<C>
instances inside its own ProcessMessage
and persists all of them to the underlying storage, and then sends each through the configured message exchange.<C,R> Completes<R> processAll(List<Source<C>> sources, Supplier<R> andThen)
processAll(List<Source<C>>)
, and also returns the Completes<R>
that provides the eventual outcome of the Supplier<R>
parameter andThen
. After all Source<C>
instances are safely persisted, the andThen
is executed and its value is given as outcome of the Completes<R>
.process...()
operations support guaranteed at-least-once delivery as long as the persistence succeeds. Additionally, these operations provide traceability from/to where and why the messages were sent and delivered, and the persistence make the messages useful in the future. It is often impossible to predict all the uses of long-term persisted messages, but they have immediate purpose and generally future applicability.send()
operations will only succeed if the messaging mechanisms successfully enqueues the message and the queue/topic/exchange is durable. However, even if the send succeeds there is no traceability from/to where and why the message was sent and delivered, nor is the message persisted long-term. In fact, the durable queue (et al) will delete the message after its deliver is confirmed.void send(Command command)
void send(DomainEvent event)
Process
types—SourcedProcess
, ObjectProcess
, and StatefulProcess
—are described in the following subsections.SourcedProcess
SourcedProcess
. Recall from the above diagram that generally a process is stimulated by a DomainEvent
and then causes the next action by emitting a Command
. The fact that Command
instances are persisted to represent the process state, this makes the process Command Sourced, as in sourced by commands.DomainEvent
instances are not received directly by the process. Instead an exchange listener receives the DomainEvent, looks up the process, and dispatches one of the process protocol messages, such as orderPlaced()
and paymentAuthorized()
.StatefulProcess
StatefulProcess
is very similar to the SourcedProcess
, except that you must implement a few overrides necessary for the StatefulProcess
and underlying StatefulEntity
abstract base type.chronicle()
is required by the StatefulProcess
, and the state()
and stateType()
are required by the StatefulEntity
.ObjectProcess
ObjectProcess
is very similar to the SourcedProcess
, except that you must implement a few overrides necessary for the ObjectProcess
and underlying ObjectEntity
abstract base type.chronicle()
is required by the ObjectProcess
, and the stateObject()
, state()
, and stateType()
are required by the ObjectEntity
.