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

瀏覽次數:74 次
跳到第一則未讀訊息

Andreas Schultz

未讀,
2021年6月22日 中午12:05:492021/6/22
收件者: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

未讀,
2021年6月23日 凌晨12:24:192021/6/23
收件者: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
回覆所有人
回覆作者
轉寄
0 則新訊息