假设我有一个包含多个子应用的伞形应用。
从根本上,mix run
或iex -S mix
(iex -S mix run
的缩写)将启动所有子应用。
从apps/app_a
开始,这些命令将启动该子应用。
有没有办法可以运行一个命令来启动子应用的特定子集?
答案 0 :(得分:2)
通常,将App A和App B一起启动的原因是A取决于B,并且在B启动之前不应该启动。在这种情况下,您可以在A的mixfile.exs
:
defp deps do
[
{:app_b, in_umbrella: true}
]
end
然后,从App A的目录开始,应用程序将首先启动App B.
有时技术上两个应用程序之间没有启动时依赖关系,但将它们组合在一起进行开发是有意义的。例如,App A将数据放在App B使用它的队列中,但它们在生产中的不同机器上运行,不会直接通信。
在这种情况下,您可以使用Application.ensure_all_started/1
在混合任务中启动每个所需的应用。例如:
defmodule Mix.Tasks.Boot do
@moduledoc """
Boots the given apps and keeps them running until killed.
## Examples
`mix boot app_a app_b`
"""
@allowed_app_names MapSet.new(~w[
app_a
app_b
app_c
])
use Mix.Task
@shortdoc "Boots the given apps"
def run(app_names) do
app_name_set = MapSet.new(app_names)
if MapSet.subset?(app_name_set, @allowed_app_names) do
app_names
|> Enum.map(&String.to_atom(&1))
|> Enum.each(fn app_name ->
start_app(app_name)
end)
# what `mix run --no-halt` does
# https://github.com/elixir-lang/elixir/blob/v1.6/lib/mix/lib/mix/tasks/run.ex#L77
Process.sleep(:infinity)
else
unknowns =
app_name_set
|> MapSet.difference(@allowed_app_names)
|> MapSet.to_list()
IO.puts("Unknown app names: #{inspect(unknowns)}")
end
end
defp start_app(:app_c = app_name) do
# Assuming app_c uses Phoenix
# what `mix phx.server` does
# https://github.com/phoenixframework/phoenix/blob/v1.3/lib/mix/tasks/phx.server.ex#L24
Application.put_env(:phoenix, :serve_endpoints, true, persistent: true)
do_start_app(app_name)
end
defp start_app(app_name) do
do_start_app(app_name)
end
defp do_start_app(app_name) do
{:ok, _apps} = Application.ensure_all_started(app_name)
end
end