我正在使用 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
我该如何处理这个问题。
Supervisor
。我链接的文档充满了可复制粘贴的示例。
当我编写需要处理 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(如果我需要其他进程来启动和关闭连接) .