Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang gen_server with long-running tasks

Good day,

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

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}

like image 554
Dfr Avatar asked Jan 16 '12 11:01

Dfr


1 Answers

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.

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
like image 172
Muzaaya Joshua Avatar answered Sep 28 '22 22:09

Muzaaya Joshua