【问题标题】:Is it okay to have logic in a supervisor?在主管中有逻辑可以吗?
【发布时间】:2017-09-16 15:39:38
【问题描述】:

我目前正在研究Elixir in Action,并且我正在重构我的Todo 应用程序代码,以便更好地掌握OTP 的主要部分。

应用程序使用的数据库只是将数据存储在磁盘上的文件中。为了确保数据库的目标文件夹存在,File.mkdir_p!(db_folder) 在数据库进程中被调用。数据库进程本身使用一堆工作进程来执行从磁盘实际存储/检索数据。

我目前所在的章节介绍了一个 DIY 进程注册表来实现更强大的监督树,通过让工作人员将自己注册到注册表并让数据库进程使用注册表查找工作人员,因此双方都可以受到监督和失败后仍然可以工作。

当 Elixir 1.4 发布时,我在补丁说明中读到了 Registry 模块,所以我想我可以重构应用程序并使用它。现在事实证明,数据库进程实际上并不需要知道数据库用于存储数据的文件夹。所以我从那个模块中取出mkdir_p! 调用并考虑把它放在哪里。我想到了两个选项:

  1. DatabaseWorker
  2. DatabaseWorkerSupervisor

我个人更喜欢第二种方法,因为如果用户没有访问持久性文件夹的权限,整个应用程序肯定会崩溃。但我不太确定是否可以将逻辑放入 Supervisor 中。

根据具体情况,将逻辑放入 Supervisor 中是不好的风格还是可以接受的?如果风格不好,如果进程崩溃,我不想重复的启动逻辑放在哪里?


我的主管代码:

defmodule Todo.DatabaseWorkerSupervisor do
  use Supervisor

  def start_link(db_folder) do
    Supervisor.start_link(__MODULE__, db_folder)
  end

  def init(db_folder) do
    File.mkdir_p!(db_folder)

    processes =
      for worker_id <- 1..3 do
        worker(Todo.DatabaseWorker, [db_folder, worker_id], id: {:dbworker, worker_id})
      end

    supervise(processes, strategy: :one_for_one)
  end
end

【问题讨论】:

    标签: elixir erlang-otp


    【解决方案1】:

    我不希望将逻辑放在主管中。如果您开始将逻辑放入主管中,您将无法通过查看您的监督树来推断崩溃/重新启动。相反,我会建议以下监督树:

    如果您将文件夹创建放在 DB gen 服务器的 init 中,DBSupervisor 将等待 init 返回,然后再转移到他的其他孩子。因此,如果文件夹创建失败,监督树的其余部分甚至都不会生成。此外,如果 DBSupervisor 策略为:rest_for_all,则 DB gen server 中的任何故障都会重新启动监督树的其余部分。

    我知道这个答案可能看起来有点矫枉过正,但如果强调纠正和学习,我认为这是正确的方向。

    一个重要的注意事项。正如您所说,使用注册表,您实际上并不需要数据库生成服务器来将任务从客户端传递给工作人员,您是对的!虽然建议的监督树看起来与注册表之前的监督树相似,但您现在应该只调用函数(可以在 DB 模块中实现)来查询注册表并将任务直接从客户端进程传递给工作人员。

    【讨论】:

    • Sasa 在几页后从Database 模块中删除了GenServer 行为,因为它不再保持状态,而只是进行注册表查找和委托。在这种情况下,您会将文件夹创建放在哪里?
    • 我认为我的建议仍然成立,即使 DB gen 服务器唯一负责的是在初始化时创建文件夹。同样,这是一种矫枉过正的做法,但我们的想法是学习正确的 OTP 开发。但也许我错了。让我们看看其他建议...
    【解决方案2】:

    如果进程崩溃,我不想重复的启动逻辑应该放在哪里?

    从主管init 调用这个似乎是合乎逻辑的地方。 特别是如果您不希望重复。

    也许代码可以在另一个模块中定义,但是从supervisor init中调用它是有意义的,如果初始化失败则让supervisor崩溃。

    【讨论】:

    • 我选择了这个答案,因为它直接回答了原始问题。但是请注意,如果我希望Database 也成为GenServer,那么this answer 会很有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2019-07-31
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    相关资源
    最近更新 更多