Create phoenix repo storage at application startup

To make deployment easier, I’ve been trying to set up the Ecto repo of a phoenix app at startup, rather than through mix tasks (that are not bundled in releases by distillery.)

There is a Ecto.Migrator class to run migrations, but mix ecto.create is still needed. I’ve resolved to using this :

  def start(_type, _args) do
    import Supervisor.Spec

    # Ensure the ecto repo has been created
    :ok = ensure_repo_created()

    # Define workers and child supervisors to be supervised
    children = [
      ... 
    ]

    ... 
    start_return = Supervisor.start_link(children, opts)

    # Run migrations
    path = Application.app_dir(:myapp, "priv/repo/migrations")
    Ecto.Migrator.run(MyApp.Repo, path, :up, all: true)

    start_return
  end

  defp ensure_repo_created() do
    case MyApp.Repo.__adapter__.storage_up(MyApp.Repo.config) do
      :ok -> :ok
      {:error, :already_up} -> :ok
      {:error, term} -> {:error, term}
    end
  end

This seems to work, but this looks a bit ugly (using the adapter), is there a cleaner / better way to do this ?

4 Likes

It’s worth noting that Distillery has some documentation around creating a task to run migrations: https://github.com/bitwalker/distillery/blob/master/docs/Running%20Migrations.md

1 Like

I’m doing the same thing, but in a release pre start hook. Its been working well for me so far.

1 Like

How do you get around the Node not running error in your pre start hook? I’m in a bit of a catch 22 where if the database isn’t created the app won’t start and if the app hasn’t started I can’t run the start function above.

Easy way to get around this is manually create the database before running but that kind of defeats the purpose of having the boot hook.

I made a package for this purpose: https://hex.pm/packages/ecto_boot_migration

1 Like