Elixir 后台运行流程

问题描述 投票:0回答:2

我正在使用 Elixir 中的 Spawn 运行一项工作,

def start_link(arg) do
    GenServer.start_link(__MODULE__, arg)
  end

def init(arg) do
    pid = spawn(fn -> connect() end)
    Process.monitor(pid)
    {:ok, arg}
  end

def connect() do
    case :gen_tcp.connect(@server_ip, @port, [:binary, {:active, false}]) do
      {:ok, tcp_socket} ->
        _output = :gen_tcp.send(tcp_socket, "S,SET PROTOCOL,6.2\r\n")
        _output = :gen_tcp.send(tcp_socket, "S,NEWSON\r\n")
        receive_news_feed_helper(tcp_socket)
        :gen_tcp.close(tcp_socket)

      {:error, _reason} ->
        connect()
    end
  end

只要我的终端出现任何错误,这个进程就会终止。

我想始终保持此进程运行,或者需要在它终止时重新启动。

我从特定地址收到新闻消息。这就是为什么使用spawn开始这个过程,但是这个过程给我发送了这样的响应:

[error] Process #PID<0.401.0> raised an exception

我该如何处理这个问题。

elixir
2个回答
2
投票

您应该在小时候就开始

Supervisor
。我链接的文档充满了可复制粘贴的示例。


0
投票

当我编写需要处理 TCP 连接的 Elixir 代码时,我通常编写的 GenServer 与您所做的没有太大不同,但使用

handle_continue
进行简单的状态转换,或者使用旧的 Connection 模块Ecto 人员(现已弃用)或 :gen_statem,但我直接调用
:tcp
模块函数而不是生成它们。我像您一样使用 Process.monitor 时可能会出现一两个例外(我想当我在 Membrane Framework 中编写具有自己的流程抽象的内容时,我曾经做过类似的事情),但如果您这样做,您需要为您将收到的
{:DOWN, ref, :process, object, reason}
消息提供 handle_info 处理程序,并决定如何处理它们(即重新启动连接、退避等)。

但在大多数情况下,来自 GenServer 或 :gen_statem 模块的直接 tcp 调用比仅为 tcp 对话生成一个附加进程要简单;我会将我的连接模型置于监督进程下,通常是 Supervisor(如果我的应用程序在启动时知道监督者要创建哪些子进程),或者 DynamicSupervisor(如果我需要其他进程来启动和关闭连接) .

© www.soinside.com 2019 - 2024. All rights reserved.