use return from gen_server:send_request/2 to match directly in handle_info/2

3 views
Skip to first unread message

Andreas Schultz

unread,
Jun 22, 2021, 12:05:49 PMJun 22
to erlang-questions
Hi,

send_request and friends are unusable in their current form.

What is required would be the ability to the RequestId returned from gen_server:send_request/2 to match the returned message (for example in the header of handle_info/2 method).
Something like this:

    handle_call(Call, From, #state{other = Other} = State) ->
        ReqId = gen_server:send_request(Other, Call),
        {noreply, State#state{pending = {ReqId, From}}}.

    handle_info({ReqId, Reply}, #state{pending = {ReqId, From}} = State) ->
        gen_server:reply(From, Reply),
       {noreply, State}.

This is currently not possible, because the internal structure of the reply message is undocumented and even changed between OTP 23 and 24.
Currently the only way to do this would be something like this for multiple outstanding requests:

    handle_info(Msg, #state{pending1 = {ReqId1, From1}, pending1 = {ReqId2, From2}, pending1 = {ReqId3, From3}} = State) ->
        case check_response(Msg, ReqId1) of
            {reply, Reply} ->
                gen_server:reply(From1, Reply);
            no_reply ->
                case check_response(Msg, ReqId2) of
                    {reply, Reply} ->
                        gen_server:reply(From2, Reply);
                    no_reply ->
                        case check_response(Msg, ReqId3) of
                            {reply, Reply} ->
                                gen_server:reply(From3, Reply);
                            no_reply ->
                                ok
                        end
                end
        end.


This could be optimized by using a map or list for the pending requests, but it would still require one to iterate over the values and check the message against each request id.

Regards,
Andreas

--
Andreas Schultz

Rickard Green

unread,
Jun 23, 2021, 12:24:19 AMJun 23
to Andreas Schultz, erlang-questions
tis 22 juni 2021 kl. 18:05 skrev Andreas Schultz <andreas...@travelping.com>:
Hi,

send_request and friends are unusable in their current form. 

That is plainly just not true. 

What is required would be the ability to the RequestId returned from gen_server:send_request/2 to match the returned message (for example in the header of handle_info/2 method).
Something like this:

    handle_call(Call, From, #state{other = Other} = State) ->
        ReqId = gen_server:send_request(Other, Call),
        {noreply, State#state{pending = {ReqId, From}}}.

    handle_info({ReqId, Reply}, #state{pending = {ReqId, From}} = State) ->
        gen_server:reply(From, Reply),
       {noreply, State}.

This is currently not possible, because the internal structure of the reply message is undocumented and even changed between OTP 23 and 24

It would have been a *major* mistake to document it. There are a lot of improvements that would be impossible to implement in a compatibile manner if it was documented. For example those improvements made in OTP 23 and 24. Be prepared for more changes introduced at any time (even in a patch). 

Currently the only way to do this would be something like this for multiple outstanding requests:

    handle_info(Msg, #state{pending1 = {ReqId1, From1}, pending1 = {ReqId2, From2}, pending1 = {ReqId3, From3}} = State) ->
        case check_response(Msg, ReqId1) of
            {reply, Reply} ->
                gen_server:reply(From1, Reply);
            no_reply ->
                case check_response(Msg, ReqId2) of
                    {reply, Reply} ->
                        gen_server:reply(From2, Reply);
                    no_reply ->
                        case check_response(Msg, ReqId3) of
                            {reply, Reply} ->
                                gen_server:reply(From3, Reply);
                            no_reply ->
                                ok
                        end
                end
        end.


This could be optimized by using a map or list for the pending requests, but it would still require one to iterate over the values and check the message against each request id.

We have on the todo list to improve handling of multiple outstanding request made via send_request() for OTP 25. 

Regards,
Rickard


Regards,
Andreas

--
Andreas Schultz
--
Rickard Green, Erlang/OTP, Ericsson AB
Reply all
Reply to author
Forward
0 new messages