通过环境。在运行时动态变量到应用程序模块?
Passing an env. variable dynamically to Application module, at runtime?
在我的 opt 应用程序中,我有一些东西在应用程序启动时得到 运行:
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
但是,我发现每当我在新服务器上部署该应用程序时,它都会无法启动,因为尚未创建数据库。即使通过控制台启动应用程序也无法解决问题,因为同样的原因它仍然会崩溃。
如何解决?
我应该引入一个布尔环境吗?变量“disable_db_related_workers”,只有当 运行 第一次在新服务器上运行该应用程序时,我才将其设置为 'true'?然后我会 运行 控制台,然后我会 运行 迁移。
$ MIX_ENV=prod DISABLE_DB_WORKERS=true ~/my_apps/my_app1/bin/my_app1 console
如果是这样,那么在Application
里面如何正确地做到这一点呢?它必须在 运行 时进行评估,也就是说,而不是在编译时。
Ecto.Migrator.up/4
是你的朋友。
它可能会直接从 Application.start/2
调用,因为它是幂等的。它可能被称为 before 在部署后立即启动应用程序。
除了这个建议,真正的实施实际上是一个品味问题。
在我的 opt 应用程序中,我有一些东西在应用程序启动时得到 运行:
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
但是,我发现每当我在新服务器上部署该应用程序时,它都会无法启动,因为尚未创建数据库。即使通过控制台启动应用程序也无法解决问题,因为同样的原因它仍然会崩溃。
如何解决?
我应该引入一个布尔环境吗?变量“disable_db_related_workers”,只有当 运行 第一次在新服务器上运行该应用程序时,我才将其设置为 'true'?然后我会 运行 控制台,然后我会 运行 迁移。
$ MIX_ENV=prod DISABLE_DB_WORKERS=true ~/my_apps/my_app1/bin/my_app1 console
如果是这样,那么在Application
里面如何正确地做到这一点呢?它必须在 运行 时进行评估,也就是说,而不是在编译时。
Ecto.Migrator.up/4
是你的朋友。
它可能会直接从 Application.start/2
调用,因为它是幂等的。它可能被称为 before 在部署后立即启动应用程序。
除了这个建议,真正的实施实际上是一个品味问题。