Как я могу загрузить подмножество приложений в зонтичном приложении?

Предположим, у меня есть приложение-зонтик, содержащее несколько дочерних приложений.

Из корня зонтика, mix run, или же iex -S mix (что сокращенно от iex -S mix run) запустит все дочерние приложения.

От apps/app_aэти команды запустят только это дочернее приложение.

Есть ли способ, которым я могу запустить одну команду, чтобы запустить определенное подмножество дочерних приложений?

1 ответ

Если есть зависимость при загрузке

Обычно причиной запуска приложения A и приложения B является то, что A зависит от B и не должен запускаться до тех пор, пока не будет запущен B. В этом случае вы можете объявить зависимость в A mixfile.exs:

defp deps do
  [
    {:app_b, in_umbrella: true}
  ]
 end

Затем, из каталога приложения A, запуск приложения сначала запустит приложение B.

Если нет зависимости при загрузке

Иногда технически нет зависимости при загрузке между двумя приложениями, но имеет смысл запускать их вместе для разработки. Например, приложение A помещает данные в очередь, из которой их использует приложение 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
Другие вопросы по тегам