Erlang gen_server具有长时间运行的任务 [英] Erlang gen_server with long-running tasks
问题描述
美好的一天,
我有一个 gen_server
进程,定期执行一些长时间运行的状态更新任务在
handle_info
:
I have a gen_server
process which does some long-running state-updating tasks periodically in
handle_info
:
handle_info(trigger, State) ->
NewState = some_long_running_task(),
erlang:send_after(?LOOP_TIME, self(), trigger),
{noreply, NewState}.
但是,当这样的任务运行时,整个服务器无响应,任何调用都会导致整个服务器崩溃:
But when such task runs, then whole server gets unresponsive and any call to it leads to whole server crash:
my_gen_server:status().
** exception exit: {timeout,{gen_server,call,[my_gen_server,status]}}
in function gen_server:call/2
如何避免阻止gen_server?
当任何时候调用 my_gen_server:status()
时,结果应该是:
{ok, task_active}
How it is possible to avoid blocking of gen_server ?
And when one call my_gen_server:status()
at any time, the result should be something like:
{ok, task_active}
推荐答案
在单独的进程中执行长时间运行的任务。让这个过程通过gen_server通知任务的进度(也就是说可以跟踪任务的进度)或者让进程完成任务或者失败,但至少告知gen_server任务的结果。
execute the long running task in a separate process. Let this process inform the gen_server of its progress with the task (that is if the task's progress can be tracked) OR let the process complete the task or fail but at least inform the gen_server of the results of the task.
让gen_server与执行此长时间运行任务的进程链接,并让gen_server知道PID或注册名称,以便在退出信号的情况下,可以将该重要的死亡过程从休息。
Let the gen_server be linked with the process doing this long running task, and let the gen_server know the PID or registered name so that in case of exit signals, it can isolate the death of that important process from the Rest.
handle_info(trigger, State) ->
Pid = spawn_link(?MODULE,some_long_running_task,[State]),
NewState = save_pid(Pid,State),
{noreply, NewState};
handle_info({'EXIT',SomePid,_},State)->
case lookup_pid(State) == SomePid of
false -> %% some other process
{noreply,State};
true ->
%% our process has died
%% what do we do now ?
%% spawn another one ?
%% thats your decision to take
....
....
{noreply,State}
end;
handle_info({finished,TaskResult},State)->
.....%% update state e.t.c.
erlang:send_after(?LOOP_TIME, self(), trigger),
{noreply,NewState}.
some_long_running_task(ServerState)->
....do work
....return results
这篇关于Erlang gen_server具有长时间运行的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!