Drop database with Elixir releases

Hi,

My Phoenix application is deployed on Gigalixir but using a database hosted on Google Cloud Platform. I use Elixir releases for deployment.

I am still in the pre-production phase of development so all I have running is a staging environment that my teammates can access and use for testing as the application is being developed. And I’m having issues dropping the database on the staging environment. I followed the method outlined in Deploying with Releases and came up with the following Backend.Release module:

defmodule Backend.Release do
  @app :backend

  def ecto_drop do
    load_app()

    for repo <- repos() do
      drop_database(repo)
    end
  end

  defp drop_database(repo) do
    case repo.__adapter__.storage_down(repo.config) do
      :ok ->
        IO.puts "The database for #{inspect repo} has been dropped"
      {:error, :already_down} ->
        IO.puts "The database for #{inspect repo} has already been dropped"
      {:error, term} when is_binary(term) ->
        raise "The database for #{inspect repo} couldn't be dropped: #{term}"
      {:error, term} ->
        raise "The database for #{inspect repo} couldn't be dropped: #{inspect term}"
    end
  end

  defp repos do
    Application.fetch_env!(@app, :ecto_repos)
  end

  defp load_app do
    Application.load(@app)
  end
end

The code for drop_database came straight from the code for ecto.drop, with the removal of references to Mix.

I run this with Gigalixir:

$ gigalixir ps:remote_console

iex > Backend.Release.ecto_drop()

** (RuntimeError) The database for Backend.Repo couldn't be dropped: ERROR 55006 (object_in_use) database "master" is being accessed by other users

There are 2 other sessions using the database.
    (backend) lib/backend/release.ex:19: Backend.Release.drop_database/1
    (backend) lib/backend/release.ex:8: anonymous fn/2 in Backend.Release.ecto_drop/0
    (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
    (backend) lib/backend/release.ex:7: Backend.Release.ecto_drop/0

I imagine the 2 sessions are:

  • the “regular” web server
  • the iex console that I just started to run the command

It seems like it’s a chicken and egg problem. To drop the database, the database can’t be accessed by others. But to be able to drop the database, I need to run an iex console, which starts a connection to the database. Or am I wrong about this?

Any thoughts on how I can drop the remote database using Elixir releases?

Thank you in advance.

Yoran

Try the following:

Enter remote console:

gigalixir ps:remote_console

Then run your command:

_build/prod/rel/release_name/bin/release_name eval "Backend.Release.ecto_drop"

This way you never need to invoke iex.

See Ecto migrations and custom commands section in phoenix documentation Deploying with Releases

3 Likes

Thanks for the proposal! But unfortunately that didn’t work either. It looks like I can’t enter a remote console on Gigalixir without having at least one replica running, thereby making it impossible to drop the database. I ended up recreating the database on GCP.