如何在伞形应用程序中启动应用程序的子集?

时间:2018-05-02 12:49:02

标签: elixir mix

假设我有一个包含多个子应用的伞形应用。

从根本上,mix runiex -S mixiex -S mix run的缩写)将启动所有子应用

apps/app_a开始,这些命令将启动该子应用

有没有办法可以运行一个命令来启动子应用的特定子集

1 个答案:

答案 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