View Source Deployment
Commanded supports running on a single node, or multiple nodes run as either a distributed Erlang cluster or as multiple single instance nodes.
Single node deployment
Running your app using Commanded on a single node requires no configuration as local is the default setting.
Multi node distributed Erlang deployment
To support deployment to a cluster of nodes and distributed Erlang you must configure:
- A registry which supports distributed Erlang. The
:global
registry provided by Commanded or the Commanded Swarm registry library. - Phoenix's distributed pub/sub and presence platform to allow process distribution and communication amongst all nodes in the cluster.
:global
registry
Use Erlang's :global
name registration facility with distributed Erlang. The global name server starts automatically when a node is started. The registered names are stored in replicated global name tables on every node. Thus, the translation of a name to a pid is fast, as it is always done locally.
Define the :global
registry for your application:
defmodule MyApp.Application do
use Commanded.Application,
otp_app: :my_app,
event_store: [
adapter: Commanded.EventStore.Adapters.EventStore,
event_store: MyApp.EventStore
],
registry: :global
end
Or configure your application to use the :global
registry in config:
# config/config.exs
config :my_app, MyApp.Application, registry: :global
Note that when clusters are formed dynamically (e.g. using libcluster]), the typical sequence of events is that first all nodes will start all processes, then the cluster is formed and :global
will kill off duplicate names. This is ugly in the logs but expected; it also means that if your supervisor's :max_restarts
is too low - lower than the number of event handlers/projectors you start - it will immediately exit and if that was your
application supervisor, your app gets shutdown. The solution is simple: keep :max_restarts
above the number of event handlers you start under your supervisor and the transition from no cluster to cluster will be clean.
Commanded Swarm registry
Add commanded_swarm_registry
to your list of dependencies in mix.exs
:
def deps do
[{:commanded_swarm_registry, "~> 1.0"}]
end
Fetch mix dependencies:
$ mix deps.get
Configure your application to use the Swarm registry:
# config/config.exs
config :my_app, MyApp.Application, registry: Commanded.Registration.SwarmRegistry
This uses the Swarm to distribute processes amongst the available nodes in the cluster.
Phoenix pub/sub
First, add it as a dependency to your project's mix.exs
file:
defp deps do
[{:phoenix_pubsub, "~> 2.0"}]
end
Fetch mix dependencies and configure the pubsub settings for your application in the environment config file:
# config/config.exs
config :my_app, MyApp.Application,
pubsub: [
phoenix_pubsub: [
adapter: Phoenix.PubSub.PG2,
pool_size: 1
]
]
The PG2 adapter is preferable for cluster deployment since it is provided by Erlang and requires no further dependencies.
EventStore
If using PostgreSQL-based Elixir EventStore please also refer to its documentation about running on a clustering of nodes.
Multi-node, but not distributed Erlang deployment
Running multiple nodes, but choosing not to connect the nodes together to form a distributed Erlang cluster, requires that you use the local registry and Phoenix's pub/sub library with its Redis adapter.
You must install and use Phoenix's pub/sub library, as described above.
Since the nodes aren't connected, you are required to use the Redis adapter as a way of communicating between the nodes. Therefore you will need to host a Redis instance for use by your app.
# config/config.exs
config :my_app, MyApp.Application,
registry: :local,
pubsub: [
phoenix_pubsub: [
adapter: Phoenix.PubSub.Redis,
host: "localhost",
port: 6379,
node_name: "localhost"
]
]