[erlang-questions] Stopping gen_server during processing

Phillips, Christopher <>
Fri Nov 8 14:17:18 CET 2013


  I suspect the right thing to do here is going to be to break up the
work. You said you have to group the records, but there's still no reason
to process them all in one go in the gen_server.

  That is, elaborating a bit on what other people have said, have one
process that receives the timer message. Have it spin up another
gen_server with the records that need processing.

  Have this spun up gen_server process records one at a time, calling cast
on itself with the remaining records after each step. Have cast handle
both this self-referential call to continue processing, and a stop
message. At any point you can send a stop message, which will always be
the next message. That is, the new gen_server will have something roughly
like (usual caveats apply to code written in an email and not run) -

  init(Records) ->
    gen_server:cast(..., process_record),
    {ok, Records}.

  handle_cast(process_record, State) ->
    case State of 
      [H | T] -> #do whatever with H,
                 gen_server:cast(..., process_record),
                 {noreply, T};
      [] -> {stop, normal, State}
    end;
  handle_cast(stop, State) ->
    {stop, normal, State}.


At any point, then, you can call gen_server:cast(..., stop), and after the
gen_server finishes processing the record it is on, it will handle the
stop message, stopping the gen_server (and with State containing the list
of unprocessed records, if you want to do something with them in the
terminate). Also note that when self-referencing like this, you need to
cast, not call (as waiting for a response from yourself will always
timeout). 

On 11/8/13, 6:00 AM, ""
<> wrote:

>On 8 nov 2013, at 10:43, Janos Hary <> wrote:
>
>>Sorry, I cannot see how could it work in Erlang.
>>I have a handle_info processing a large number of records:
>>handle_info(check, State) ->
>>	check_records(State).
>>check_records(State) ->
>>	do some work...
>>	case State#stop_flag of
>>		true ->
>>			{stop, normal, State};
>>		_ ->
>>			check_records(State)
>>	end.
>>The State in check_records cannot changed from another cast. I'm not even
>>sure that the cast will execute before check_records finishes.
>>Janos
>>-----Original Message-----
>>From: 
>>[mailto:] On Behalf Of Bengt Kleberg
>>Sent: Friday, November 08, 2013 9:28 AM
>>To: undisclosed-recipients:
>>Cc: 
>>Subject: Re: [erlang-questions] Stopping gen_server during processing
>>These are my opinions, not hard facts.
>>Add a member to the gen_server state record that says that you are going
>>to
>>stop when possible. Use a cast to set it to true when you want to stop.
>>If
>>it is true and you can stop the gen_server, stop it.
>>bengt
>>On Fri, 2013-11-08 at 08:55 +0100, Janos Hary wrote:
>>>All,
>>>I have a gen_server process which periodically processes new records
>>>from a database. I use timer:send_after to schedule gathering and
>>>processing new records. I can gracefully stop the gen_server when it
>>>is waiting, but I need a way to stop it during processing. Of cause I
>>>only want to stop it at certain points of the processing, for example
>>>before starting to process the next record. I need to group the
>>>records, so I cannot ask them one by one from the db.
>>>What is the preferred way of doing this?
>>>Thanks for your answers in advance.
>>>Janos
>>>_______________________________________________
>>>erlang-questions mailing list
>>>
>>>http://erlang.org/mailman/listinfo/erlang-questions
>>_______________________________________________
>>erlang-questions mailing list
>>
>>http://erlang.org/mailman/listinfo/erlang-questions
>>_______________________________________________
>>erlang-questions mailing list
>>
>>http://erlang.org/mailman/listinfo/erlang-questions





More information about the erlang-questions mailing list