In my opt application I have some stuff that gets run on application boot:
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
{Phoenix.PubSub, [name: MyApp.PubSub, adapter: Phoenix.PubSub.PG2]},
{MyAppLib.Repo, []},
{MyAppWeb.Endpoint, []},
{MyAppLib.Cache, []},
# these are GenServer-s, some may work with a database
{MyApp.Worker1, []}, # 1
{MyApp.Worker2, []}, # 2
{MyApp.Initializer, []} # 3
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
However, I've found out that whenever I deploy the app on a new server, it'll fail to start up because a database hasn't been created yet. And even starting the application via console won't solve the problem because it'll still crash due to the same reason.
How to fix it?
Should I introduce a boolean env. variable "disable_db_related_workers" which I'd set to 'true' only when running the app the first time on a new server? Then I'd run console and from it I'd run the migrations.
$ MIX_ENV=prod DISABLE_DB_WORKERS=true ~/my_apps/my_app1/bin/my_app1 console
If so, how to do this properly inside Application
then? It'll have to be evaluated at runtime, that is, not at compilation.
Ecto.Migrator.up/4
is your friend.
It might be called from Application.start/2
directly because it’s idempotent. It might be called before starting the application right after deploy.
Besides this advice, the real implementation is actually a matter of taste.