Current section

Files

Jump to
commanded lib commanded application supervisor.ex
Raw

lib/commanded/application/supervisor.ex

defmodule Commanded.Application.Supervisor do
@moduledoc false
use Supervisor
alias Commanded.Application.Config
@doc """
Retrieves the compile time configuration.
"""
def compile_config(application, opts) do
otp_app = Keyword.fetch!(opts, :otp_app)
env_opts = Application.get_env(otp_app, application, [])
config = Keyword.merge(opts, env_opts)
{otp_app, config}
end
@doc """
Retrieves the runtime configuration.
"""
def runtime_config(application, otp_app, config, opts) do
config =
config
|> Keyword.merge(opts)
|> Keyword.put(:otp_app, otp_app)
|> Keyword.put(:application, application)
case application_init(application, config) do
{:ok, config} -> {:ok, config}
:ignore -> :ignore
end
end
@doc """
Starts the application supervisor.
"""
def start_link(application, otp_app, config, name, opts) do
Supervisor.start_link(
__MODULE__,
{application, otp_app, config, name, opts},
name: name
)
end
def init({application, otp_app, config, name, opts}) do
case runtime_config(application, otp_app, config, opts) do
{:ok, config} ->
{event_store_child_spec, config} = event_store_child_spec(name, config)
{pubsub_child_spec, config} = pubsub_child_spec(name, config)
{registry_child_spec, config} = registry_child_spec(name, config)
:ok = Config.associate(self(), name, config)
children =
event_store_child_spec ++
pubsub_child_spec ++
registry_child_spec ++
app_child_spec(name, config)
Supervisor.init(children, strategy: :one_for_one)
:ignore ->
:ignore
end
end
defp app_child_spec(name, config) do
task_dispatcher_name = Module.concat([name, Commanded.Commands.TaskDispatcher])
aggregates_supervisor_name = Module.concat([name, Commanded.Aggregates.Supervisor])
subscriptions_name = Module.concat([name, Commanded.Subscriptions])
registry_name = Module.concat([name, Commanded.Subscriptions.Registry])
snapshotting = Keyword.get(config, :snapshotting, %{})
hibernate_after = Keyword.get(config, :hibernate_after, :infinity)
[
{Task.Supervisor, name: task_dispatcher_name, hibernate_after: hibernate_after},
{Commanded.Aggregates.Supervisor,
name: aggregates_supervisor_name,
application: name,
snapshotting: snapshotting,
hibernate_after: hibernate_after},
{Commanded.Subscriptions.Registry,
application: name, name: registry_name, hibernate_after: hibernate_after},
{Commanded.Subscriptions,
application: name, name: subscriptions_name, hibernate_after: hibernate_after}
]
end
defp event_store_child_spec(name, config) do
{adapter, adapter_config} =
Commanded.EventStore.adapter(name, Keyword.get(config, :event_store))
{:ok, child_spec, adapter_meta} = adapter.child_spec(name, adapter_config)
config = Keyword.put(config, :event_store, {adapter, adapter_meta})
{child_spec, config}
end
defp pubsub_child_spec(name, config) do
{adapter, adapter_config} =
Commanded.PubSub.adapter(name, Keyword.get(config, :pubsub, :local))
{:ok, child_spec, adapter_meta} = adapter.child_spec(name, adapter_config)
config = Keyword.put(config, :pubsub, {adapter, adapter_meta})
{child_spec, config}
end
defp registry_child_spec(name, config) do
{adapter, adapter_config} =
Commanded.Registration.adapter(name, Keyword.get(config, :registry, :local))
{:ok, child_spec, adapter_meta} = adapter.child_spec(name, adapter_config)
config = Keyword.put(config, :registry, {adapter, adapter_meta})
{child_spec, config}
end
defp application_init(application, config) do
if Code.ensure_loaded?(application) and function_exported?(application, :init, 1) do
application.init(config)
else
{:ok, config}
end
end
end