elixir - 在 Elixir 中部署时更改后端/模块?

标签 elixir phoenix-framework

如何实现一个可替换的后端(或基本上任何部分或模块),以便可以在 Elixir 的配置/部署时替换它?

我的具体情况是一个简单的网络应用程序(在这种情况下使用 Phoenix,但我猜这个问题也适用于其他情况)我有一个非常简单的后端使用 Agent保持状态,但我认为 future 需要能够或多或少地动态切换后端。

我猜 Ecto 和 Logger 都在某种程度上做到了这一点,但对于 Elixir 的新手来说,很难知道去哪里找。

最佳答案

这可以通过向主管提出的论点来处理。例如,Ecto 的后端主管接受一个名为 adapter 的参数。指定应使用哪种数据库:

# https://github.com/elixir-lang/ecto/blob/364d34bb135e2256fd48327464ada7f7fa2976f9/lib/ecto/repo/backend.ex#L13-L16

def start_link(repo, adapter) do
  # Start Ecto, depending on the supplied <repo> and <adapter>
end

你可以在你的应用程序中做同样的事情,可能是 start_link 的一个参数。就足够了——我们称之为backend
# my_app/lib/my_app/supervisor.ex

defmodule MyApp.Supervisor do
  def start_link(backend) do
    # use <backend> as you need to in here,
    # it will contain the module that is
    # specified in the configuration file.
  end
end

现在,您当然可以在启动应用程序时根据配置文件动态设置该参数:
# my_app/lib/my_app.ex

defmodule MyApp do
  use Application

  def start(_type, _args) do
    MyApp.Supervisor.start_link(backend)
  end

  # get backend from configuration
  def backend do
    # ???
  end
end

现在,唯一缺少的部分是如何从配置文件中获取后端。对此没有单一的答案,因为有多种方法可以做到这一点。

混合配置

您可以简单地使用现有的 Mix 配置,但它的缺点是每次配置更改时都需要重新编译应用程序:
# my_app/config/config.exs

use Mix.Config
config :my_app, backend: MyApp.SpecificBackend

然后调整您的应用程序以读取指定的后端:
# my_app/lib/my_app.ex

defmodule MyApp do
  use Application

  def start(_type, _args) do
    # same as above ...
  end

  def backend do
    Application.get_env(:my_app, :backend)
  end
end

自己滚

您还可以实现自己的配置文件。我不在这里详细介绍,但这是一个粗略的想法:
  • 在某处保存配置文件
  • 在 Elixir
  • 中阅读解析它
  • 使用 String.to_existing_atom("Elixir.#{module_name}") 将字符串转换为模块名称
  • 如果原子(因此模块名称)不存在,这将引发错误
  • 在您的 def backend 中使用它功能

  • 使用现有的运行时配置库

    基本上是先前解决方案的美化版本。谷歌搜索了一下,我发现了一个名为 Conform 的库。 .它看起来很有趣,但我无法做出任何 promise ,因为我自己从未使用过它。

    关于elixir - 在 Elixir 中部署时更改后端/模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27280964/

    相关文章:

    unicode - 在 Elixir 中计算字符串中的代码点

    maps - 如何访问复杂的元组/ map Elixir

    elixir - 这个 Ecto Constraint Error 试图告诉我什么?

    elixir - with..do..else 语句中出现奇怪的语法错误

    elixir - 在 Phoenix 中使用 Ecto 获取数据时仅获取特定字段

    controller - HTTP 状态代码作为 put_status 中的原子

    elixir - 如何在 phoenix 上显示完整的回溯

    elixir - 验证一个日期比另一个日期晚或相同

    elixir - 如何处理 Elixir/Phoenix 模板中的空案例?

    elixir - 当计算机别名具有连字符时尝试连接节点时出现 "(ArithmeticError) bad argument in arithmetic expression"