From 1ddf9cbddd051894b2aabede01b65fa969b6d132 Mon Sep 17 00:00:00 2001 From: Nick Kezhaya Date: Thu, 17 Oct 2019 17:25:15 -0500 Subject: [PATCH] Migrate on startup --- config/config.exs | 14 ---- lib/stripe_mock/application.ex | 3 +- lib/stripe_mock/migrator.ex | 73 +++++++++++++++++++ lib/stripe_mock/repo.ex | 22 +++++- .../plug/ensure_migrator_finished.ex | 11 +++ lib/stripe_mock_web/router.ex | 1 + 6 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 lib/stripe_mock/migrator.ex create mode 100644 lib/stripe_mock_web/plug/ensure_migrator_finished.ex diff --git a/config/config.exs b/config/config.exs index 12dae8f..589bc42 100644 --- a/config/config.exs +++ b/config/config.exs @@ -24,20 +24,6 @@ config :logger, :console, # Use Jason for JSON parsing in Phoenix config :phoenix, :json_library, Jason -{uri, _} = System.cmd("pg_tmp", ["-t"]) - -[username, host, port, database] = - Regex.scan(~r/(\w+)@([\w\d\.]+)\:(\d+)\/(\w+)/i, uri, capture: :all_but_first) |> List.flatten() - -config :stripe_mock, StripeMock.Repo, - username: username, - password: "", - database: database, - hostname: host, - port: port, - pool_size: 2, - migration_primary_key: [name: :id, type: :binary_id] - # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/lib/stripe_mock/application.ex b/lib/stripe_mock/application.ex index b6a4e3f..ce6ef42 100644 --- a/lib/stripe_mock/application.ex +++ b/lib/stripe_mock/application.ex @@ -6,7 +6,8 @@ defmodule StripeMock.Application do def start(_type, _args) do children = [ StripeMockWeb.Endpoint, - StripeMock.Repo + StripeMock.Repo, + StripeMock.Migrator ] opts = [strategy: :one_for_one, name: StripeMock.Supervisor] diff --git a/lib/stripe_mock/migrator.ex b/lib/stripe_mock/migrator.ex new file mode 100644 index 0000000..52bb8f7 --- /dev/null +++ b/lib/stripe_mock/migrator.ex @@ -0,0 +1,73 @@ +defmodule StripeMock.Migrator do + use GenServer + + def start_link(default) do + GenServer.start_link(__MODULE__, default, name: __MODULE__) + end + + def done? do + GenServer.call(__MODULE__, :done?) + end + + @impl true + def init(_arg) do + migrate() + + {:ok, nil} + end + + @impl true + def handle_call(:done?, _from, state) do + {:reply, true, state} + end + + @start_apps [ + :crypto, + :ssl, + :postgrex, + :ecto, + :ecto_sql + ] + + @repos [StripeMock.Repo] + + def migrate(_argv \\ nil) do + # Start apps necessary for executing migrations + IO.puts("Starting dependencies") + Enum.each(@start_apps, &Application.ensure_all_started/1) + + Application.load(:basic_space) + + # Start the Repo(s) for app + # Switch pool_size to 2 for ecto > 3.0 + IO.puts("Starting repos") + Enum.each(@repos, & &1.start_link(pool_size: 2)) + + # Run migrations + Enum.each(@repos, &run_migrations_for/1) + + # Done + IO.puts("Success!") + end + + defp run_migrations_for(repo) do + app = Keyword.get(repo.config, :otp_app) + migrations_path = priv_path_for(repo, "migrations") + IO.puts("Running migrations for #{app}, from #{migrations_path}") + Ecto.Migrator.run(repo, migrations_path, :up, all: true) + end + + defp priv_path_for(repo, filename) do + app = Keyword.get(repo.config, :otp_app) + + repo_underscore = + repo + |> Module.split() + |> List.last() + |> Macro.underscore() + + priv_dir = "#{:code.priv_dir(app)}" + + Path.join([priv_dir, repo_underscore, filename]) + end +end diff --git a/lib/stripe_mock/repo.ex b/lib/stripe_mock/repo.ex index 187555f..3a3e264 100644 --- a/lib/stripe_mock/repo.ex +++ b/lib/stripe_mock/repo.ex @@ -1,9 +1,29 @@ defmodule StripeMock.Repo do use Ecto.Repo, otp_app: :stripe_mock, adapter: Ecto.Adapters.Postgres import Ecto.Changeset - alias Ecto.Changeset alias StripeMock.API + @impl true + def init(_type, config) do + {uri, _} = System.cmd("pg_tmp", ["-t"]) + + [[username, host, port, database]] = + Regex.scan(~r/(\w+)@([\w\d\.]+)\:(\d+)\/(\w+)/i, uri, capture: :all_but_first) + + config = + Keyword.merge(config, + username: username, + password: "", + database: database, + hostname: host, + port: port, + pool_size: 2, + migration_primary_key: [name: :id, type: :binary_id] + ) + + {:ok, config} + end + def fetch(schema, id) do with true <- valid_id?(id), %{} = object <- get(schema, id) do diff --git a/lib/stripe_mock_web/plug/ensure_migrator_finished.ex b/lib/stripe_mock_web/plug/ensure_migrator_finished.ex new file mode 100644 index 0000000..c057d1b --- /dev/null +++ b/lib/stripe_mock_web/plug/ensure_migrator_finished.ex @@ -0,0 +1,11 @@ +defmodule StripeMockWeb.Plug.EnsureMigratorFinished do + def init(arg) do + arg + end + + def call(conn, _arg) do + true = StripeMock.Migrator.done?() + + conn + end +end diff --git a/lib/stripe_mock_web/router.ex b/lib/stripe_mock_web/router.ex index 092fdc4..cdd1b6b 100644 --- a/lib/stripe_mock_web/router.ex +++ b/lib/stripe_mock_web/router.ex @@ -4,6 +4,7 @@ defmodule StripeMockWeb.Router do pipeline :api do plug :accepts, ["json"] plug StripeMockWeb.Plug.Auth + plug StripeMockWeb.Plug.EnsureMigratorFinished end scope "/v1", StripeMockWeb do