Migration breaks in release with Ecto 3

Hi Elixirforum,

I’m stuck on an error with my Ecto migration in a release built with distillery 2. It works with mix and it used to work before I upgraded to Ecto 3:

** (exit) exited in: GenServer.call(Ecto.Migration.Supervisor, {:start_child, [#PID<0.151.0>, Manager.Repo, :forward, :up, %{level: :info, sql: false}]}, :infinity)                                              
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started                                                 
    (elixir) lib/gen_server.ex:914: GenServer.call/3
    (ecto_sql) lib/ecto/migration/runner.ex:22: Ecto.Migration.Runner.run/7
    (ecto_sql) lib/ecto/migrator.ex:211: Ecto.Migrator.attempt/7
    (ecto_sql) lib/ecto/migrator.ex:113: anonymous fn/4 in Ecto.Migrator.do_up/4
    (ecto_sql) lib/ecto/migrator.ex:193: anonymous fn/3 in Ecto.Migrator.run_maybe_in_transaction/5
    (ecto_sql) lib/ecto/adapters/sql.ex:787: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4                                                                                                        
    (db_connection) lib/db_connection.ex:1341: DBConnection.run_transaction/4
    (ecto_sql) lib/ecto/migrator.ex:192: Ecto.Migrator.run_maybe_in_transaction/5
make: *** [Makefile:61: migrate] Error 1

Here is my migration module:

defmodule Manager.ReleaseTasks do

  @apps [:manager, :chercheville]

  @start_apps [
    :crypto,
    :ssl,
    :postgrex,
    :ecto,
  ]

  def repos(app), do: Application.get_env(app, :ecto_repos, []) |> IO.inspect

  def migrate do
    start_services()

    run_migrations()

    stop_services()
  end

  def start_services do
    for app <- @apps do
      # Start apps necessary for executing migrations
      IO.puts("Starting dependencies..")
      Enum.each(@start_apps, &Application.ensure_all_started/1)

      # Start the Repo(s) for app
      IO.puts("Starting repos..")
      Enum.each(repos(app), & &1.start_link(pool_size: 2))
    end
  end

  def stop_services do
    IO.puts("Success!")
    :init.stop()
  end

  defp run_migrations() do
    IO.puts("Running migrations..")
    for app <- @apps do
      Enum.each(repos(app), &run_migrations_for/1)
    end
  end

  defp run_migrations_for(repo) do
    app = Keyword.get(repo.config, :otp_app)
    IO.puts("Running migrations for #{app}..")
    migrations_path = priv_path_for(repo, "migrations")
    Ecto.Migrator.run(repo, migrations_path, :up, all: true)
  end

  def priv_path_for(repo, filename) do
    app = Keyword.get(repo.config, :otp_app)
    repo_underscore = repo |> Module.split() |> List.last() |> Macro.underscore()
    Path.join([priv_dir(app), repo_underscore, filename])
  end

  def priv_dir(app), do: "#{:code.priv_dir(app)}"
end

Any pointer would be appreciated as I don’t really know where to start to solve this.

You’re not starting ecto_sql

7 Likes

@LostKobrakai Thank you very much! Now it works!

2 Likes

I also added some functions for creating databases:

  def createdb do
    prepare()
    Enum.each(repos(), &createdb_for/1)
    IO.puts("Creating successful!")
  end

  defp createdb_for(repo) do
    app = Keyword.get(repo.config, :otp_app)
    IO.puts("Running creation db for #{app}")
    repo.__adapter__.storage_up(repo.config)
  end

And after first run I got this output:

Loading auction..
Starting dependencies..
Starting repos..
Running creation db for auction
02:12:32.413 [error] Postgrex.Protocol (#PID<0.131.0>) failed to connect: ** (Postgrex.Error) FATAL 3D000 (invalid_catalog_name) database "auction" does not exist
02:12:32.413 [error] Postgrex.Protocol (#PID<0.130.0>) failed to connect: ** (Postgrex.Error) FATAL 3D000 (invalid_catalog_name) database "auction" does not exist
Creating successful!

But all subsequent runs go without errors.
Why?