[erlang-questions] gen_server loop pattern
Nathaniel Waisbrot
nathaniel@REDACTED
Fri Dec 4 18:24:24 CET 2015
I've been writing worker-processes that are mostly non-interactive as
gen_servers.
It looks something like this (skipping the boring bits, but I can include a
full example if this is unclear):
```
-module(fetcher).
-behavior(gen_server).
init(State) ->
gen_server:cast(?MODULE, start),
{ok, State}.
handle_cast(start, State) ->
reschedule(State),
{noreply, State};
handle_cast(loop, State) ->
{Work, State1} = pull_from_queue(State),
worker_pool:task(Work),
reschedule(State1),
{noreply, State1};
handle_cast({checkpoint, CheckpointData}, State) ->
State1 = do_checkpoint(CheckpointData, State),
{noreply, State1}.
reschedule(State) ->
timer:apply_after(State#state.delay_ms, gen_server, cast, [?MODULE,
loop]).
```
It feels like I ought to use some other pattern, but I don't know what.
There's a few reasons that I've chosen gen_server:
* It's easy. The gen_server behavior is simple and I've already written
plenty of them.
* I can hook it easily to get some simple debug capability. I often add a
```
handle_call(get_state, _From, State) -> {reply, State, State}.
```
* Likewise, I can pause and restart the worker by writing a few very simple
handle_* functions.
* The "checkpoint" message is used to send a checkpoint request to all
workers and then record a safe spot in the queue once I get a reply back
from all of them. This doesn't have to be in the `fetcher` module, but once
it's already a gen_server it seems easy to wedge it in.
Is there a better way to do this?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20151204/d56d505e/attachment.htm>
More information about the erlang-questions
mailing list