Commanded.Application behaviour (Commanded v1.3.0) View Source
Defines a Commanded application.
The application expects at least an :otp_app option to be specified. It
should point to an OTP application that has the application configuration.
For example, the application:
defmodule MyApp.Application do
use Commanded.Application, otp_app: :my_app
router(MyApp.Router)
endCould be configured with:
# config/config.exs
config :my_app, MyApp.Application
event_store: [
adapter: Commanded.EventStore.Adapters.EventStore,
event_store: MyApp.EventStore
],
pubsub: :local,
registry: :localAlternatively, you can include the configuration when defining the application:
defmodule MyApp.Application do
use Commanded.Application,
otp_app: :my_app,
event_store: [
adapter: Commanded.EventStore.Adapters.EventStore,
event_store: MyApp.EventStore
],
pubsub: :local,
registry: :local
router(MyApp.Router)
endA Commanded application must be started before it can be used:
{:ok, _pid} = MyApp.Application.start_link()Instead of starting the application manually, you should use a Supervisor.
Supervision
Use a supervisor to start your Commanded application:
Supervisor.start_link([
MyApp.Application
], strategy: :one_for_one)Command routing
Commanded applications are also composite routers allowing you to include one or more routers within an application.
Example
defmodule MyApp.Application do
use Commanded.Application, otp_app: :my_app
router(MyApp.Accounts.Router)
router(MyApp.Billing.Router)
router(MyApp.Notifications.Router)
endSee Commanded.Commands.CompositeRouter for details.
Command dispatch
Once a router has been configured you can dispatch a command via the application:
:ok = MyApp.dispatch(command, opts)See dispatch/1 and dispatch/2 for details.
Dynamic named applications
An application can be provided with a name as an option to start_link/1.
This can be used to start the same application multiple times, each using its
own separately configured and isolated event store. Each application must be
started with a unique name.
Multipe instances of the same event handler or process manager can be started by refering to a started application by its name. The event store operations can also be scoped to an application by referring to its name.
Example
Start an application process for each tenant in a multi-tenanted app, guaranteeing that the data and processing remains isolated between tenants.
for tenant <- [:tenant1, :tenant2, :tenant3] do
{:ok, _app} = MyApp.Application.start_link(name: tenant)
endTypically you would start the applications using a supervisor:
children =
for tenant <- [:tenant1, :tenant2, :tenant3] do
{MyApp.Application, name: tenant}
end
Supervisor.start_link(children, strategy: :one_for_one)To dispatch a command you must provide the application name:
:ok = MyApp.Application.dispatch(command, application: :tenant1)Default dispatch options
An application can be configured with default command dispatch options such as
:consistency, :timeout, and :returning. Any defaults will be used
unless overridden by options provided to the dispatch function.
defmodule MyApp.Application do
use Commanded.Application,
otp_app: :my_app,
default_dispatch_opts: [
consistency: :eventual,
returning: :aggregate_version
]
endSee the Commanded.Commands.Router module for more details about the
supported options.
Telemetry
[:commanded, :application, :dispatch, :start]- Description: Emitted when an application starts dispatching a command
- Measurements:
%{system_time: integer()} - Metadata:
%{application: Commanded.Application.t(), execution_context: Commanded.Aggregates.ExecutionContext.t()}
[:commanded, :application, :dispatch, :stop]- Description: Emitted when an application stops dispatching a command
- Measurements:
%{duration: non_neg_integer()} - Metadata:
%{application: Commanded.Application.t(), execution_context: Commanded.Aggregates.ExecutionContext.t(), error: nil | any()}
Link to this section Summary
Callbacks
Returns the application configuration stored in the :otp_app environment.
Dispatch a registered command.
Dispatch a registered command.
A callback executed when the application starts.
Starts the application supervisor.
Shuts down the application.
Link to this section Types
Specs
t() :: module()
Link to this section Callbacks
Specs
config() :: Keyword.t()
Returns the application configuration stored in the :otp_app environment.
Specs
dispatch(command :: struct()) :: :ok | {:ok, aggregate_state :: struct()} | {:ok, aggregate_version :: non_neg_integer()} | {:ok, execution_result :: Commanded.Commands.ExecutionResult.t()} | {:error, :unregistered_command} | {:error, :consistency_timeout} | {:error, reason :: term()}
Dispatch a registered command.
commandis a command struct which must be registered with aCommanded.Commands.Routerand included in the application.
Specs
dispatch( command :: struct(), timeout_or_opts :: non_neg_integer() | :infinity | Keyword.t() ) :: :ok | {:ok, aggregate_state :: struct()} | {:ok, aggregate_version :: non_neg_integer()} | {:ok, execution_result :: Commanded.Commands.ExecutionResult.t()} | {:error, :unregistered_command} | {:error, :consistency_timeout} | {:error, reason :: term()}
Dispatch a registered command.
commandis a command struct which must be registered with aCommanded.Commands.Routerand included in the application.timeout_or_optsis either an integer timeout or a keyword list of options.The timeout must be an integer greater than zero which specifies how many milliseconds to allow the command to be handled, or the atom
:infinityto wait indefinitely. The default timeout value is five seconds. Alternatively, an options keyword list can be provided, it supports the following options. Options:causation_id- an optional UUID used to identify the cause of the command being dispatched.correlation_id- an optional UUID used to correlate related commands/events together.consistency- one of:eventual(default) or:strong. By setting the consistency to:stronga successful command dispatch will block until all strongly consistent event handlers and process managers have handled all events created by the command.metadata- an optional map containing key/value pairs comprising the metadata to be associated with all events created by the command.returning- to choose what response is returned from a successful command dispatch. The default is to return an:ok. The available options are::aggregate_state- to return the update aggregate state in the successful response:{:ok, aggregate_state}.:aggregate_version- to include the aggregate stream version in the successful response:{:ok, aggregate_version}.:execution_result- to return aCommanded.Commands.ExecutionResultstruct containing the aggregate's identity, version, and any events produced from the command along with their associated metadata.false- don't return anything except an:ok.
timeout- as described above.
Returns :ok on success unless the :returning option is specified where
it returns one of {:ok, aggregate_state}, {:ok, aggregate_version}, or
{:ok, %Commanded.Commands.ExecutionResult{}}.
Returns {:error, reason} on failure.
Example
command = %OpenAccount{account_number: "ACC123", initial_balance: 1_000}
:ok = BankApp.dispatch(command, timeout: 30_000)
Specs
A callback executed when the application starts.
It must return {:ok, keyword} with the updated list of configuration.
Specs
start_link(opts :: Keyword.t()) :: {:ok, pid()} | {:error, {:already_started, pid()}} | {:error, term()}
Starts the application supervisor.
Returns {:ok, pid} on sucess, {:error, {:already_started, pid}} if the
application is already started, or {:error, term} in case anything else goes
wrong.
Specs
Shuts down the application.