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

问题描述

在我的 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 调用,因为它是幂等的。它可能在部署后立即启动应用程序之前被调用。

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