传递一个环境。动态变量到应用程序模块,在运行时?

Posted

技术标签:

【中文标题】传递一个环境。动态变量到应用程序模块,在运行时?【英文标题】:Passing an env. variable dynamically to Application module, at runtime? 【发布时间】:2021-09-22 04:45:29 【问题描述】:

在我的 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 中正确执行此操作?它必须在运行时进行评估,而不是在编译时。

【问题讨论】:

【参考方案1】:

Ecto.Migrator.up/4 是你的朋友。

它可能会直接从Application.start/2 调用,因为它是幂等的。它可能在部署后立即启动应用程序之前调用。

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

【讨论】:

我已经有一个运行迁移的模块,它是代码中提到的那些“工人”之一。也就是说,它必须在 Application 的哪个位置被准确地调用?作为start(_type, _args)的第一个命令? 开始回购之前。第一行有效,是的。 我不确定这在未创建数据库时是否会有所帮助,我们有一个使用 repo.__adapter__.storage_up/1 的服务器,但我通常会手动创建数据库。 @Daniel 问题明确指出问题与迁移有关。但是,是的,通常您的评论完全有道理。

以上是关于传递一个环境。动态变量到应用程序模块,在运行时?的主要内容,如果未能解决你的问题,请参考以下文章

在运行时将环境变量传递给 Vue 应用程序

Svelte 框架:在运行时将环境变量传递给客户端包

跨语言共享环境变量

传递动态内存

你可以将环境变量传递给xcodebuild吗?

如何将值传递给 Gitlab CI 作业