Elixir 在控制器内启动进程
考虑这样的模块:Elixir 在控制器内启动进程,elixir,phoenix-framework,Elixir,Phoenix Framework,考虑这样的模块: defmodule Sampple do def start(nick, password, state \\ %State{}) do {:ok, client} = ExIrc.start_client! GenServer.start(__MODULE__, [%{state | client: client, nick: nick, pass: password }] ) e
defmodule Sampple do
def start(nick, password, state \\ %State{}) do
{:ok, client} = ExIrc.start_client!
GenServer.start(__MODULE__,
[%{state | client: client,
nick: nick,
pass: password
}]
)
end
def enter(nick, token) do
Logger.debug "Sending message"
start(nick, token)
end
#another irrelevant callbacks
def handle_info({:joined, _}, state) do
ExIrc.Client.msg(state.client,
:privmsg,
state.channel,
"!enter")
{:stop, :normal, state}
end
end
这样的GenServer在Phoenix CopController中被实例化如下:
defmodule Cgas.Controller do
use Cgas.Web, :controller
require Logger
def enter(conn, _args) do
Logger.debug inspect(get_session(conn, :login))
%{"login" => login,
"token" => token } = get_session(conn, :login)
{:ok, pid} = Sample.enter(login, token)
Logger.debug inspect(pid)
json conn, %{"success" => "true "}
end
end
如果从repl或非控制器进程调用enter
,则没有问题,尽管从控制器操作内部调用时,进程处于活动状态,但不执行任何操作。此示例模块用作ExIRC处理程序。原因
首先,控制器都是独立的进程。这意味着当用户发出请求时,进程启动,当他得到响应时,进程终止。
通过使用start_链接启动进程,可以创建一个双向链接,使死亡事件传播到其他链接的进程。也就是说,如果你有如下连接:
Cgas.Controller <----> Sample
Cgas.Controller示例
这意味着如果Sample
或Cgas.Controller
中的任何一个死亡,它们都将死亡。根据控制器如何工作的内部系统,这意味着Sample
只要客户端连接到服务器(通常为1-100ms),它就会一直存在
这可能就是你注意到它“什么都不做”的原因,因为它生命中没有足够的时间(可怜的东西)
解决方案
您可以做的第一件事就是简单地用start/2
而不是start\u link/2
启动流程,但是它会为向服务器发出的每个请求创建一个流程,而这很可能最终成为一个僵尸流程大军
如果你真的坚持这样做,你可以给它一段时间去生活。类似于进程和进程的寄存器:#如果客户端在X秒内没有发出任何新请求,就自杀
:erlang.exit self,:'die!'代码>
但一般来说,这是对web框架的“火与忘”规则的挑战,最好使用像WebSockets这样的实时连接,并使过程与连接的寿命一样长 原因
首先,控制器都是独立的进程。这意味着当用户发出请求时,进程启动,当他得到响应时,进程终止。
通过使用start_链接启动进程,可以创建一个双向链接,使死亡事件传播到其他链接的进程。也就是说,如果你有如下连接:
Cgas.Controller <----> Sample
Cgas.Controller示例
这意味着如果Sample
或Cgas.Controller
中的任何一个死亡,它们都将死亡。根据控制器如何工作的内部系统,这意味着Sample
只要客户端连接到服务器(通常为1-100ms),它就会一直存在
这可能就是你注意到它“什么都不做”的原因,因为它生命中没有足够的时间(可怜的东西)
解决方案
您可以做的第一件事就是简单地用start/2
而不是start\u link/2
启动流程,但是它会为向服务器发出的每个请求创建一个流程,而这很可能最终成为一个僵尸流程大军
如果你真的坚持这样做,你可以给它一段时间去生活。类似于进程和进程的寄存器:
#如果客户端在X秒内没有发出任何新请求,就自杀
:erlang.exit self,:'die!'代码>
但一般来说,这是对web框架的“火与忘”规则的挑战,最好使用像WebSockets这样的实时连接,并使过程与连接的寿命一样长 start
具有相同的效果start
具有相同的效果从repl调用哪个enter?如何验证进程是否处于活动状态?我通过process.alive?
检查进程是否处于活动状态。我在repl中调用了它,并且enter
works.Which enter。其中有两个是enter
from sample,它启动进程。哪个enter是从repl调用的?如何验证进程是否处于活动状态?我通过process.alive?
检查进程是否处于活动状态。我在repl中调用了它,并且enter
works.Which enter。其中有两个从示例中输入,它启动了一个过程。