Forwarding and effects in JavaScript

A command can only act on one component at a time—​the component that received the command. For certain use cases, you might want a different component to handle the command. Rather than sending an immediate reply to a command, the receiving component can forward the command to another component. In cases where you want other components to be aware that a component processed a command, you can emit an effect.

Handle forwarding and emit effects by wrapping the return value into a reply. The reply holds a regular return message or a forward to another component. Both can carry effects that notify other components.

The forwarding or effect can target any component within the service—​whether it is an instance of the same or different type of component.

Transactional limitations

It’s important to note that forwarded commands, and commands emitted as side effects, are non-atomic—​there is no guarantee that any one sent transactions will succeeded. If the service, or the data store, fails, while a forwarded command is executing, the triggering command responds with an error (so the client can retry), but there is no automatic rollback.

If partial updates will cause problems, do not use forwarding and effects to update multiple entities at once. In this case emit an event that is (eventually) processed by all subscribers.

See the documentation on Publishing and subscribing.

Forwarding control to another component

To forward a command return a forward reply that includes the call to invoke, and the message to invoke it with. The command is not forwarded until any state actions requested by the command handler are successfully completed. It is the responsibility of the component receiving the forward to return a reply that matches the type of the original command. Forwards can be chained arbitrarily long.

Use case: processing messages and triggering commands

An action might listen to a journal or an external topic and trigger commands on entities based on the incoming messages.

Forwarding a command

The CommandContextnew tab can call the method forwardnew tab to forward the command to another entity service call.

Emitting effects on another component

An entity may also emit one or more effects. An effect is something whose result has no impact on the result of the current command—​if it fails, the current command still succeeds. The result of the effect is therefore ignored. Effects are only performed after the successful completion of any state actions requested by the command handler.

There is no guarantee that an effect will be executed successfully. If a failure occurs after the command is fully handled, effects might not be executed. Effects are not retried in case of failures.

Effects may be declared as synchronous or asynchronous. Asynchronous commands run in a "fire and forget" fashion. The code flow of the caller (the command handler of the entity which emitted the asynchronous command) continues while the command is being asynchronously processed. Meanwhile, synchronous commands run sequentially, that is, the commands are processed in order, one at a time. The final result of the command handler, either a reply or a forward, is not sent until all synchronous commands are completed.

Use case: mobile notification

You might want to emit effects to notify interested parties of a change in state. For example, after a withdrawal is made from a bank account, an account entity could send a notification to the account owner’s mobile phone.

Emitting an effect

The CommandContextnew tab for each entity type implements EffectContextnew tab, which is able to emit an effect after processing the command by invoking the method effectnew tab