【问题标题】:Elixir: Loop the actor to rerun itselfElixir:循环演员以重新运行自己
【发布时间】:2017-09-17 15:08:51
【问题描述】:

我正在制作一个主从应用程序。主代码如下。此代码在start_link异步调用worker。一旦工人完成他们的工作,他们就会使用handle_cast异步调用向主人报告。在此之后,我打算保留主actor 'ON' 以便它可以重新生成新的worker Actors(就像它在第一次start_link 调用中所做的那样。)。然而,一旦所有的工人演员都完成了他们的工作,主人就会停下来。这个stackoverflow 帖子提到使用递归调用,但我无法使用Genserver 来做到这一点。 Genserver有什么方法可以实现吗?

defmodule Bitcoin.MasterNode do
use GenServer

def start_link(opts) do
    {:ok, pid} = GenServer.start_link(__MODULE__,:ok, opts)
    start_workers(----perform some task asynchronously----)
    {:ok, pid}
end

def set_message(server, name) do
    GenServer.cast(server, {:set_message, name})
end

#callbacks
def init(:ok) do
    names = []
    {:ok, names}
end

def handle_cast({:set_message, name},names) do
    names = names ++ name
    IO.puts name
    {:noreply,names}
end

结束

编辑:我正在分布式模式下运行应用程序,即主节点也连接到外部工作节点。如果 Master 死了,连接也会消失。目的是保持具有相同 PID 的主节点运行无限次。

【问题讨论】:

  • 请不要使用代码格式来强调,使用强调来强调(查看我的编辑以了解如何。)
  • 你不需要递归调用来保持 GenServer 活着。 GenServer 将保持活动状态,直到它被明确停止(或由于错误而崩溃)。我在您的代码 sn-p 中看不到任何会使 GenServer 停止的代码。 start_workers 会停止这个 GenServer 吗?
  • “目的是让具有相同 PID 的主节点无限运行。”——这是不可能的。请改用命名服务器。名称不会随着服务器重新启动而更改。
  • 我正在使用escript.build 而不是iex shell 运行代码。当工人完成他们的工作并且没有更多的行可供主人计算时,代码就会停止。我希望我能够表达我的担忧。
  • @COSTA 创建一个混合应用程序并将其作为 OTP 应用程序运行,不要试图用螺丝刀敲钉子。脚本是用来运行脚本的,默认情况下是启动、完成它们的工作并终止。将应用程序用于长时间运行的进程。

标签: elixir gen-server


【解决方案1】:

如果我正确理解了您的意图,您希望在所有孩子完成后立即重新开始整个过程​​。如果这是真的,人们应该使用 OTP 功能而不是自己发明轮子 :)

只需用一个监督者扩展监督树,这将监督你的“主人”(Bitcoin.MasterNode,),你已经准备好了

会发生什么:

  1. MasterSupervisor 开始;
  2. MasterSupervisor 透明地启动 MasterNode 作为具有 :one_for_one 策略的工作人员;
  3. MasterNode 的行为与现在完全一样;
  4. 一旦所有工作人员完成,MasterNode死亡,这很好;
  5. 一旦它的孩子MasterNode 死了,MasterSupervisor 会根据它的策略自动重启它

要跟踪GenServer,无论是否重生,都应该使用named servers 而不是仅仅操作PIDs:

GenServer.start_link(__MODULE__,:ok, name: MyWorker)

【讨论】:

  • 我的错。我还希望应用程序以分布式模式运行。如果主人死了,外部工人也会死。我已经更新了这个问题。我们还能做一些灵丹妙药吗?
  • @mudasobwa:我是 Erlang(和 Elixir)的新手,并不完全理解主管的概念。如果进程失败,而不是成功完成,主管不应该重新启动进程。 OP 在 cmets 中提到,工作线程在死前调用 Bitcoin.MasterNode.set_message,如果我在他的位置,我会从 set_message 生成新进程来替换旧进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2014-11-10
相关资源
最近更新 更多