Erlang gen_server 具有长时间运行的任务

标签 erlang erlang-otp gen-server

美好的一天,

我有一个 gen_server 进程,它定期执行一些长时间运行的状态更新任务 handle_info:

handle_info(trigger, State) ->
    NewState = some_long_running_task(),
    erlang:send_after(?LOOP_TIME, self(), trigger),
    {noreply, NewState}.

但是当这样的任务运行时,整个服务器将变得无响应,并且对它的任何调用都会导致整个服务器崩溃:

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() 时,结果应该类似于: {确定,task_active}

最佳答案

在单独的进程中执行长时间运行的任务。让此进程通知 gen_server 其任务进度(即是否可以跟踪任务进度),或者让进程完成任务或失败,但至少通知 gen_server 任务结果。

让 gen_server 与执行此长时间运行任务的进程链接,并让 gen_server 知道 PID 或注册名称,以便在出现退出信号时,它可以将该重要进程的死亡与其余进程隔离开来。

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 具有长时间运行的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8879177/

相关文章:

erlang - OTP 行为 : gen_fsm; gen_event. 实际例子?

erlang - 如何使用 io:getline/1 解决 io :setopts([{echo, false 中的限制}])

erlang - Erlang( cometd 聊天)中的消息队列模型?

erlang - gen_server 启动了吗?

erlang - gen_server:调用未注册的全局名称

Erlang 异步消息处理与 gen_server :cast/2

functional-programming - 如何在 Erlang 二进制文件中一次高效地设置一位而不需要命令式?

elixir - 如何从 List 中创建多个 GenServer 进程并映射存储在其中的数据?

event-handling - 我可以在 C 节点中获得 Erlang OTP 行为吗?

Elixir 主管 - 你如何命名受监督的任务