Перенос данных из другого репо в экто-миграцию - PullRequest
0 голосов
/ 17 апреля 2020

Аналогично этому вопросу: Используя репо в Ecto-миграции , у меня есть Ecto-миграция, где я хотел бы создать несколько новых таблиц, но также перенести некоторые данные из различных хранилище. Например:

defmodule MyApp.Repo.Migrations.CreateFoo do
  use Ecto.Migration
  import Ecto.Query

  def change do
    create table(:foo) do
      add(:status, :text)
    end

    flush()
    execute &import_from_AnotherApp/0
  end

  defp import_from_AnotherApp()
    foos = from(f in AnotherApp.Foo, where: ...)
           |> AnotherApp.Repo.all

    Enum.each(foos, fn(foo) ->
      # Insert data from AnotherApp into MyApp foo table
    end)

  end
end

Проблема в том, что при запуске mix ecto.migrate я получаю

** (RuntimeError) could not lookup Ecto repo AnotherApp.Repo because it was not started or it does not exist

Я пытался добавить AnotherApp в качестве зависимости MyApp в mix.exs, но Я все еще получаю ту же ошибку.

Можно ли это сделать?

1 Ответ

1 голос
/ 18 апреля 2020

Когда вы запускаете смешанные задачи, они запускаются в своих собственных процессах, поэтому другие приложения (включая основное приложение, содержащее задачу) могут не запускаться.

Иногда вам приходится вставлять подобные строки в свой пользовательский. Смешайте задачи, и я подозреваю, что вы могли бы поместить их в свои миграции:

{:ok, _} = Application.ensure_all_started(:my_app)
{:ok, _} = Application.ensure_all_started(:another_app)

Однако иногда недостаточно убедиться, что они запущены: иногда вам нужно явно запустить процесс. В вашем случае вам придется запустить другое приложение Ecto.Repo. Обычно вы запускаете свои репозитории Ecto , перечисляя их в супервизоре вашего приложения внутри application.ex, например

def start(_type, _args) do
  children = [
    {MyApp.Repo, []},
    {AnotherApp.Repo, []},
  ]

  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Но если это другое приложение не нужно запускать для вашего приложения обычные функции, затем вы можете запустить процесс вручную, запустив MyApp.Repo.start_link([]). - вы можете добавить это в свою миграцию, чтобы посмотреть, подходит ли она:

x = MyApp.Repo.start_link([])
IO.inspect(x)

Если вам повезет, вы получите :ok и идентификатор процесса, но если нет, вам следует получить некоторые полезные отладочная информация.

Надеюсь, это поможет.

...