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

在Elixir中部署时更改后端/模块?,elixir,phoenix-framework,Elixir,Phoenix Framework,如何实现一个可替换的后端(或基本上任何部分或模块),以便在Elixir中配置/部署时替换它 我的具体情况是一个简单的web应用程序(在本例中使用Phoenix,但我猜这个问题也适用于其他情况),其中我有一个非常简单的后端,使用Agent保持状态,但我认为未来需要能够或多或少地动态切换后端 我猜Ecto和Logger都在某种程度上做到了这一点,但作为长生不老药的新手,很难知道该去哪里寻找。这可以通过与主管的争论来解决。例如,Ecto的后端主管使用一个名为adapter的参数来指定应使用哪种数据库:

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

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


我猜Ecto和Logger都在某种程度上做到了这一点,但作为长生不老药的新手,很难知道该去哪里寻找。

这可以通过与主管的争论来解决。例如,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
现在,您当然可以根据配置文件在启动应用程序时动态设置该参数:

# 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
现在,唯一缺少的是如何从配置文件获取后端。没有单一的答案,因为有多种方法可以做到这一点

混合配置 您可以简单地使用现有的混合配置,但它有一个缺点,即您需要在每次配置更改时重新编译应用程序:

# 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
滚你自己的 您还可以实现自己的配置文件。我不打算在这里详述,但这是一个粗略的想法:

  • 在某处保存一个配置文件
  • 读一篇用长生不老药解析的文章
  • 将字符串转换为具有
    string.to_existing_atom(“Elixir.#{module_name}”)的模块名
  • 如果atom(因此模块名)不存在,这将引发错误
  • def后端
    功能中使用它
使用现有的运行时配置库
基本上是以前解决方案的美化版本。我在谷歌上搜索了一下,发现了一个叫做。它看起来很有趣,但我无法做出任何承诺,因为我自己从未使用过它。

谢谢,我有很多好的线索。我猜我也可以使用混合环境来拥有不同的后端?很高兴我能帮上忙。是的,你说得对。当然,您也可以使后端依赖于您的混合环境,但它仍然需要您在更改环境时重新编译应用程序。
# 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