<div dir="ltr"><div>Ahhh.. I was not familiar with how the noreply response works from handle_call. If I'm understanding it correctly though, in the snippet he provided, I would need to change {reply, Message, NewState} to instead call gen_server:reply/2 which then unblocks the caller. That is exactly what I am needing. I figured there had to be something to do that without having to cobble together some cludgy code. </div><div><br></div><div>Thanks.</div><div><br></div><div>-- Chris</div><span style="color:rgb(50,56,54);font-family:Verdana,Geneva,Helvetica,Arial,sans-serif;font-size:13.44px;background-color:rgb(242,241,237)"><div><br></div></span></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Oct 1, 2017 at 2:44 PM, Mikael Pettersson <span dir="ltr"><<a href="mailto:mikpelinux@gmail.com" target="_blank">mikpelinux@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>See Vlad's reply a few days ago.  What you're describing is easily solvable by:<br></div>1. having the gen_server's handle_call for this API call stash away the From and uuid in its internal state and return noreply as that blocks the caller, and<br></div>2. when the response comes in (tagged with that uuid) match it to the corresponding From and gen_server:reply to that one, which unblocks the caller.<br><br></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Oct 1, 2017 at 7:22 PM, Chris Waymire <span dir="ltr"><<a href="mailto:chris@waymire.net" target="_blank">chris@waymire.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I'll try to provide some context around what I am doing. Basically I am writing a client for a custom MQTT network that in addition to the basic MQTT functionality also provides a request/response system. So the idea here is that when a user of the app executes the "request" function a uuid will be attached to their message payload and published onto the network. Another endpoint that is subscribed to that topic will receive the message, process it, and publish a response with a reference to the original message id. The original sender then picks up this message and accepts it as the response to their request. There's more going on there but that's the gist of it. So which the request function is called I need the caller to block, but not the MQTT client itself as it will still need to be processing messages on the network. <br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 29, 2017 at 12:40 AM, zxq9 <span dir="ltr"><<a href="mailto:zxq9@zxq9.com" target="_blank">zxq9@zxq9.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On 2017年09月29日 金曜日 16:23:42 zxq9 wrote:<br>
> On 2017年09月28日 木曜日 17:58:08 Chris Waymire wrote:<br>
> > handle_call({request, Data#data{uid=UID}}, _From, State) -><br>
> >     make_asycnc_req(Data),<br>
> >     receive<br>
> >         {UID, Response} -> {reply, Response, State}<br>
> >     end.<br>
> ><br>
> > handle_info({response, Response#response{uid=UID}}, State) -><br>
> >     self() ! {UID, Response},<br>
> >     {noreply, State}.<br>
><br>
><br>
> Your naked `receive` will work just fine. The flow of the process has never<br>
> returned to the gen_server module yet to await another message to dispatch,<br>
> so when you write a naked `receive` in some handling code that is exactly<br>
> where the process will block, and you can receive any arbitrary thing you<br>
> want there. Just be careful not to match on any system or gen_server message<br>
> types and you'll get the behavior you expect (though your mailbox may be<br>
> filling up with other stuff in the meantime).<br>
<br>
</span>One note of caution is that you might actually be fighting against the<br>
natural order of things. Consider carefully whether you need this and what<br>
it is achieving for you. You may really be better off with casts. See if<br>
there is a way for you to design the system to be entirely async, and if<br>
not, why not. What state is being async going to threaten? Is it an<br>
ordering issue? Are you relaying a message and waiting for a response<br>
that will be returned? If so, why is the originating process not just<br>
receiving the response directly? (Do you really need a middle-man?)<br>
<br>
Another way to achieve this without blocking is to use references to<br>
tag messages and keep a digest of them. That prevents your gen_server<br>
from becoming unresponsive to system messages or blocking indefinitely<br>
in the event the sender of the message you are waiting on crashes.<br>
<br>
This is actually what the `From` argument to handle_call/3 is for:<br>
<br>
handle_call({request, Data = data{uid = UID}},<br>
            {Sender, Tag},<br>
            State = #s{queue = Q}) -><br>
    ok = make_async_request(Data, Tag),<br>
    {noreply, State#s{queue = [{{Tag, UID, Sender} | Queue]}};<br>
% ...<br>
<br>
handle_cast({response, {Tag, UID}, Message}, State = #s{queue = Queue}) -><br>
    case lists:keyfind(Tag, 1, Queue) of<br>
        Ticket = {Tag, UID, Sender} -><br>
            NewState = State#s{queue = lists:delete(Ticket, Queue)},<br>
            {reply, Message, NewState};<br>
        false -><br>
            LogString = "Received bad message: ~tp",<br>
            ok = log(warning, LogString, [{{Tag, UID}, Message}]),<br>
            {noreply, State}<br>
    end;<br>
% ...<br>
<br>
There may be any number of ways you might want to phrase that or structure<br>
it, but basically that's how you can safely stow such a pending response<br>
value and sender, and get the response back out to them without any weird<br>
blockages or unresponsiveness.<br>
<div class="m_-2078105276212598388m_-6481425581061703106HOEnZb"><div class="m_-2078105276212598388m_-6481425581061703106h5"><br>
-Craig<br>
______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/list<wbr>info/erlang-questions</a><br>
</div></div></blockquote></div><br></div></div></div>
<br>______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/list<wbr>info/erlang-questions</a><br>
<br></blockquote></div><br></div>
</div></div></blockquote></div><br></div>