<div dir="ltr"><div><div><div><div><div><div>I've been writing worker-processes that are mostly non-interactive as gen_servers. <br><br></div><div>It looks something like this (skipping the boring bits, but I can include a full example if this is unclear):<br><br><br>```<br></div><div>-module(fetcher).<br></div><div>-behavior(gen_server).<br><br></div><div>init(State) -><br></div><div>  gen_server:cast(?MODULE, start),<br></div><div>  {ok, State}.<br><br></div><div>handle_cast(start, State) -><br></div><div>  reschedule(State),<br></div><div>  {noreply, State};<br></div>handle_cast(loop, State) -><br><div>  {Work, State1} = pull_from_queue(State),<br></div><div>  worker_pool:task(Work),<br></div><div>  reschedule(State1),<br></div><div>  {noreply, State1};<br></div><div>handle_cast({checkpoint, CheckpointData}, State) -><br></div><div>  State1 = do_checkpoint(CheckpointData, State),<br></div><div>  {noreply, State1}.<br><br></div><div>reschedule(State) -><br></div><div><div>  timer:apply_after(State#state.delay_ms, gen_server, cast, [?MODULE, loop]).<br>```<br></div><br>It feels like I ought to use some other pattern, but I don't know what.<br><br>There's a few reasons that I've chosen gen_server:<br><br></div>* It's easy. The gen_server behavior is simple and I've already written plenty of them.<br></div>* I can hook it easily to get some simple debug capability. I often add a <br></div>    ```<br>    handle_call(get_state, _From, State) -> {reply, State, State}.<br>    ```<br></div>* Likewise, I can pause and restart the worker by writing a few very  simple handle_* functions.<br></div>* 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.<br><br><br></div>Is there a better way to do this?<br></div>