<div style="font-family: Helvetica; font-size: 12px; ">Vineet,</div><div style="font-family: Helvetica; font-size: 12px; "><br></div><div style="font-family: Helvetica; font-size: 12px; ">Using standard OTP behaviours for handling processes is not a bad practice.</div><div style="font-family: Helvetica; font-size: 12px; ">It helps to always have unified predictable behaviour of the processes you spawn.</div><div style="font-family: Helvetica; font-size: 12px; "><br></div><div style="font-family: Helvetica; font-size: 12px; "> </div><div style="font-family: Helvetica; font-size: 12px; ">I will just enumerate several examples hoping those would be helpful for you:</div><div style="font-family: Helvetica; font-size: 12px; ">* process A queries process B for something:</div><div style="font-size: 12px; "> [in A] </div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">      </span>{ok, Result} = gen_server:call( B, {request, Something}, CallTimeout ).</font></div><div style="font-family: Helvetica; font-size: 12px; "><br></div><div style="font-family: Helvetica; font-size: 12px; ">* procerss A asks B to do something but does not expect any response on this action:</div><div style="font-size: 12px; "><span style="font-family: Helvetica; "> [in A] </span></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">  </span>ok = gen_server:cast( B, {ack, ID} ).</font></div><div style="font-family: Helvetica; font-size: 12px; "><br></div><div style="font-family: Helvetica; font-size: 12px; ">* process A queries B for some results.</div><div style="font-family: Helvetica; font-size: 12px; "> Yet the query cannot be satisfied but will be once some event will be reported to B</div><div style="font-family: Helvetica; font-size: 12px; "><br></div><div style="font-size: 12px; "><span style="font-family: Helvetica; "> [in A]</span></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space: pre; ">   </span>it_occurred = gen_server:call( B, i_will_wait_for_a_while, infinity ).</font></div><div style="font-size: 12px; "><font face="Courier New"><br></font></div><div style="font-family: Helvetica; font-size: 12px; "> [in B]</div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space: pre; ">   </span>handle_call( i_will_wait_for_a_while, From, State = #s{ reply_queue = Q } ) -></font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">          </span> {no_reply, State #s{reply_queue = queue:in( From , Q )} };</font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">           </span>…</font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">        </span>handle_cast( the_event_i_told_you_about,  State = #s{ reply_queue = Q }) -></font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">                </span>{ReplyTo, NewQ} = queue:out( Q ),</font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">          </span> _Ignored = gen_server:reply( ReplyTo, it_occured  ),</font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">            </span>{no_reply, State #s{ reply_queue = NewQ }};</font></div><div style="font-size: 12px; "><font face="Courier New"><span class="Apple-tab-span" style="white-space: pre; ">             </span>...</font></div>
                <div><div><span style="font-size: 12px;">In this very case it's probably better to think about employing gen_fsm behaviour - to handle the states like probably 'starving', 'caught_up', 'lagging' etc…</span></div><div><br></div><div><span style="font-size: 12px; ">* Say we are handling some named resources each with one process.</span></div><div><span style="font-size: 12px; ">   A client code if wants to interact with the resource needs to get the pid of the process owning the resource.</span></div><div><span style="font-size: 12px; ">   A client code knows the name of the resource only.</span></div><div><span style="font-size: 12px; "><br></span></div><div><span style="font-size: 12px; ">resource_owner.erl:</span></div><div><div><span style="font-family: 'Courier New'; ">maybe_start_resource_owner( ResourceName ) -></span></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre"> </span>case catch supervisor:start_link( resource_owners_sup , { ResourceName }) of</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">           </span>{ ok, Pid } -> ok;</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">          </span>ignore -> ok</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">        </span>end.</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">init({ ResourceName }) -></font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">   </span>case catch gproc:add_local_name( {resource_owner, ResourceName} ) of</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">           </span>true -></font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space: pre; ">                  </span>{ok, #s{ resource_name = ResourceName }};</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">              </span>_ -></font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">                        </span>ignore</font></div><div><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre"> </span>end.</font></div></div><div><font face="Courier New"><br></font></div><div><span style="font-size: 12px;">client_code.erl:</span></div><div><span style="font-size: 12px;"><font face="Courier New">get_owner_pid_by_resource_name( ResourceName ) -></font></span></div><div><span style="font-size: 12px;"><span class="Apple-tab-span" style="white-space:pre"><font face="Courier New"> ok = resource_owner:maybe_start_resource_owner( ResourceName ),</font></span></span></div><div><span style="font-size: 12px;"><span class="Apple-tab-span" style="white-space:pre"><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">     </span>{ResourceOwnerPid, _} = gproc:await( {n, l, {resource_owner, ResourceName} } ),</font></span></span></div><div><span style="font-size: 12px;"><span class="Apple-tab-span" style="white-space:pre"><font face="Courier New"><span class="Apple-tab-span" style="white-space:pre">        </span>{ok, ResourceOwnerPid}.</font></span></span></div><div><br></div><div><span style="font-size: 12px;">The main moral here - use the standard behaviours when spawning your processes. </span></div><div><span style="font-size: 12px;">The OTP team has solved most of the potential problems for you already :)</span></div><div><br></div><div>--</div><div>RG</div><div><br></div></div>
                 
                <p style="color: #A0A0A8;">On Friday, November 30, 2012 at 12:49 pm, Vineet Naik wrote:</p>
                <blockquote type="cite" style="border-left-style:solid;border-width:1px;margin-left:0px;padding-left:10px;">
                    <span><div><div><div>Hi Roman,</div><div><br></div><div>Thanks for replying.</div><div><br></div><div>I think gen_server pretty much fits my case. But I would like to</div><div>know whether it's fine to use gen_server if the model is not</div><div>strictly based on client-server message passing. Does Erlang have</div><div>any thing like "abuse of the gen_server" anti-pattern :-) ?</div><div><br></div><div>Regards,</div><div>Vineet</div><div><br></div><div><br></div><div>On Fri, Nov 30, 2012 at 2:06 PM, Roman Gafiyatullin</div><div><<a href="mailto:r.gafiyatullin@me.com">r.gafiyatullin@me.com</a>> wrote:</div><blockquote type="cite"><div><div>Hi,</div><div><br></div><div>In most of the cases one shall not use "simple loop functions": raw process</div><div>cannot participate properly in the supervision tree.</div><div><br></div><div>If you need some new tricky specific model of behaving - better implement it</div><div>over gen_server.</div><div>For instance supervisor is a gen_server :)</div><div><br></div><div>If you need something more low level - use 'gen' module (see how gen_fsm is</div><div>implemented).</div><div><br></div><div>--</div><div>Regards</div><div>RG ( +375 33 602 5080, UTC+3 )</div><div><br></div><div>On Friday, November 30, 2012 at 11:25 am, Vineet Naik wrote:</div><div><br></div><div>Hello,</div><div><br></div><div>I am an Erlang newbie and trying to write a simple chat bot as an</div><div>XMPP external component. I am using exmpp library and following</div><div>along these tutorials[1]</div><div><br></div><div>So far I have one module `bot_server` that uses the gen_server</div><div>interface. Inside it's `handle_info` callback, incoming messages</div><div>from various client will be received. To handle and reply to the</div><div>these messages, I am thinking of spawning a "bot" process per</div><div>client. It will stay alive as long as the client is available</div><div>ie. when the client sends "unavailable" presence, it will die. I</div><div>also need to keep a list of all the alive bot processes in the</div><div>bot_server's state.</div><div><br></div><div>My question is, would it be appropriate to implement the bot as a</div><div>gen_server too considering that it needs to handle two calls, one</div><div>for handling incoming message (asynchronous) and second for</div><div>killing itself (synchronous)?</div><div><br></div><div>In general, when should one use gen_server and when should</div><div>one write a simple loop function?</div><div><br></div><div>[1] exmpp tutorials:</div><div><a href="http://blog.process-one.net/scalable_xmpp_bots_with_erlang_and_exmpp_part_i/">http://blog.process-one.net/scalable_xmpp_bots_with_erlang_and_exmpp_part_i/</a></div><div><br></div><div>Thanks,</div><div>Vineet</div><div>_______________________________________________</div><div>erlang-questions mailing list</div><div><a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a></div><div><a href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a></div></div></blockquote><div><br></div><div><br></div><div><br></div><div>-- </div><div>Vineet Naik</div></div></div></span>
                 
                 
                 
                 
                </blockquote>
                 
                <div>
                    <br>
                </div>