通过环境。在运行时动态变量到应用程序模块?

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 在部署后立即启动应用程序。

除了这个建议,真正的实施实际上是一个品味问题。