Elixir 主管有逻辑可以吗?
我目前正在使用Elixir,我正在对我的Elixir 主管有逻辑可以吗?,elixir,otp,Elixir,Otp,我目前正在使用Elixir,我正在对我的Todo应用程序代码进行重构,以便更好地掌握OTP的主要部分 应用程序使用的数据库只是将数据存储在磁盘上的文件中。要确保数据库的目标文件夹存在,File.mkdir\p!(db_folder)在数据库进程内调用。数据库进程本身使用一组工作进程来执行实际的磁盘数据存储/检索 我目前所在的章节介绍了一个DIY流程注册表,通过让工作人员将自己注册到注册表,并让数据库流程查找使用注册表的工作人员,实现了一个更健壮的监督树,这样双方都可以受到监督,并且在失败后仍然可
Todo
应用程序代码进行重构,以便更好地掌握OTP的主要部分
应用程序使用的数据库只是将数据存储在磁盘上的文件中。要确保数据库的目标文件夹存在,File.mkdir\p!(db_folder)
在数据库进程内调用。数据库进程本身使用一组工作进程来执行实际的磁盘数据存储/检索
我目前所在的章节介绍了一个DIY流程注册表,通过让工作人员将自己注册到注册表,并让数据库流程查找使用注册表的工作人员,实现了一个更健壮的监督树,这样双方都可以受到监督,并且在失败后仍然可以工作
当Elixir1.4面世时,我在补丁说明中读到了注册表
模块,所以我想我可能会重构应用程序并使用它。现在,事实证明,数据库进程实际上不必知道数据库用于存储数据的文件夹。所以我拿了mkdir\p代码>调用该模块并考虑将其放置在何处。我想到两个选择:
DatabaseWorker
DatabaseWorkerSupervisor
我个人更喜欢第二种方法,因为如果用户没有访问持久性文件夹的权限,整个应用程序肯定会崩溃。但我不太确定把逻辑放在一个主管身上是否合适
根据具体情况,将逻辑放在主管的风格中是错误的还是可以接受的?如果是糟糕的风格,我应该把启动逻辑放在哪里?如果进程崩溃,我不想重复启动逻辑
我的主管代码:
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
defmodule Todo.databaseworker supervisor do
使用主管
def start_链接(db_文件夹)do
Supervisor.start\u链接(\u模块\u,db\u文件夹)
终止
def init(db_文件夹)do
File.mkdir_p!(db_文件夹)
进程=
对于worker_id,我不希望将逻辑放在主管中。如果您开始在管理器中添加逻辑,您无法通过查看管理树来解释崩溃/重启的原因。相反,我将建议以下监督树:
如果将文件夹创建放在DB gen服务器的init
中,DBSupervisor将等待init
返回,然后再转到其他子文件夹。因此,如果文件夹创建失败,则监管树的其余部分甚至不会生成。此外,如果DBSupervisor策略是:rest\u for_all
,则DB gen服务器中的任何故障都将重新启动监控树的其余部分
我知道这个答案似乎有些过分,但如果重点放在纠正和学习上,我认为这是正确的方向
一个重要的提示。正如您所说的,有了注册中心,您就不需要DB gen服务器来将任务从客户端传递给工作者,您是对的!尽管建议的监控树看起来与注册表之前的监控树相似,但您现在应该只调用函数(可以在DB模块中实现)来查询注册表,并将任务直接从客户端进程传递给工作进程。我不希望将逻辑放在监控树中。如果您开始在管理器中添加逻辑,您无法通过查看管理树来解释崩溃/重启的原因。相反,我将建议以下监督树:
如果将文件夹创建放在DB gen服务器的init
中,DBSupervisor将等待init
返回,然后再转到其他子文件夹。因此,如果文件夹创建失败,则监管树的其余部分甚至不会生成。此外,如果DBSupervisor策略是:rest\u for_all
,则DB gen服务器中的任何故障都将重新启动监控树的其余部分
我知道这个答案似乎有些过分,但如果重点放在纠正和学习上,我认为这是正确的方向
一个重要的提示。正如您所说的,有了注册中心,您就不需要DB gen服务器来将任务从客户端传递给工作者,您是对的!尽管建议的监控树看起来与注册表之前的监控树相似,但现在您应该只调用函数(可以在DB模块中实现)来查询注册表并将任务直接从客户端进程传递给工作进程
如果进程崩溃,我不想重复的启动逻辑应该放在哪里
从supervisorinit
调用这个似乎是合乎逻辑的。
特别是如果你不想重复的话
也许代码可以在另一个模块中定义,但是从supervisor init调用它是有意义的,如果初始化失败,让supervisor崩溃
如果进程崩溃,我不想重复的启动逻辑应该放在哪里
从supervisorinit
调用这个似乎是合乎逻辑的。
特别是如果你不想重复的话
也许代码可以在另一个模块中定义,但从supervisor init调用它是有意义的,如果初始化失败,让supervisor崩溃。Sasa将在几页之后从数据库
模块中删除GenServer行为,因为它不再保持状态,只执行注册表查找和委派。在这种情况下,您会将文件夹创建放在哪里?我认为我的建议仍然有效,即使DB gen服务器只负责初始化时的文件夹创建。同样,这是一种过分的做法,但其目的是学习适当的OTP开发。但也许我错了。让我们看看其他建议……Sasa在几页之后从数据库
模块中删除GenServer行为,因为它不再保持状态,而只是执行注册表