erlang 返回handle_call值时在case_clause中抛出错误

mxg2im7a  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(231)

I want the handle_call \ 3 to return me a tuple of the following form {message, timestamp, integer} and then in the case clause, it gives me an error when I should enter through the branch corresponding to that response.
Attach an example

execute(Method, Url, Headers, Body, PoolId) ->
    BeforeGetConn = erlang:now(),
    TimeStartBusy = undefined,
    PosBusy = undefined,
    TimeStartBusyAfterWait = undefined,
    PosBusyAfterWait = undefined,
    TimeInWaiting = undefined,
    PosWaiting = undefined,
    ShouldContinue =
    case gen_server:call(?MODULE, {get_conn, PoolId, self(), BeforeGetConn}) of
        proceed -> ok;
        {wait, Ref, PosWaiting} ->
            ...
        %Throw error in the following line
        {proceed, TimeStartBusy, PosBusy} -> {ok, TimeStartBusy, PosBusy};
        unknown_pool -> ...
    end,
    case ShouldContinue of
        {ok, TimeStartBusy, PosBusy}  ->
           execute_process(...);
        ...
    end.

handle_call({get_conn, PoolId, Caller, Time}, _From, #state{pools = Pools} = State) ->
  case proplists:get_value(PoolId, Pools) of
    undefined ->
      ...
    Pool ->
      case is_busy_full(Pool) of
        false ->
          Pool2 = add_to_busy({Caller}, Pool),
          TimeStartBusy = os:timestamp(),
          PosBusy = queue:len(Pool2#pool.busy),
          {reply,
          {proceed, TimeStartBusy, PosBusy},
          State#state{pools = [{PoolId, Pool2} |
                                proplists:delete(PoolId, Pools)]}};
        true ->
          ...
      end
  end;

The error I see on the console is the following:
exit with reason: {[{reason,{case_clause,{proceed,{1614,588434,663546},1}}}
Thank you
Code edited:

ShouldContinue =
    case gen_server:call(?MODULE, {get_conn, PoolId, self(), BeforeGetConn}) of
        proceed -> ok;
        {wait, Ref, PosWaiting} ->
            receive
                {proceed, Ref, TimeStartBusyAfterWait, PosBusyAfterWait, TimeInWaiting} ->
                TimeStartBusy = undefined, 
                PosBusy = undefined,
                {ok, TimeStartBusy, PosBusy, TimeInWaiting, PosWaiting, TimeStartBusyAfterWait, PosBusyAfterWait}
            after ?CONF_BACKEND_HTTP_TIMEOUT ->
                ok
            end;
        {proceed, TimeStartBusy, PosBusy} -> 
            PosWaiting = undefined,
            TimeStartBusyAfterWait = undefined, 
            PosBusyAfterWait = undefined, 
            TimeInWaiting = undefined,
            {ok, TimeStartBusy, PosBusy, TimeInWaiting, PosWaiting, TimeStartBusyAfterWait, PosBusyAfterWait};
        unknown_pool -> unknown_pool
end,
case ShouldContinue of
    {ok, TimeStartBusy, PosBusy, TimeInWaiting, PosWaiting, TimeStartBusyAfterWait, PosBusyAfterWait}  ->
         execute_process(BeforeGetConn, Url, Headers, Body, Method, PoolId, TimeStartBusy, PosBusy, TimeStartBusyAfterWait, PosBusyAfterWait, PosWaiting, TimeInWaiting);
    ok ->
        execute_process(BeforeGetConn, Url, Headers, Body, Method, PoolId, undefined, undefined, undefined, undefined, undefined, undefined);
    unknown_pool ->
         ...
end.
qcuzuvrc

qcuzuvrc1#

发生这种情况的原因是,在函数的开头将TimeStartBusyPosBusy设置为undefined,因此case子句{proceed, TimeStartBusy, PosBusy}只能匹配元组{proceed, undefined, undefined}。实际值为{proceed,{1614,588434,663546},1},因此不匹配。
与大多数其他语言不同,Erlang变量是单赋值的:一旦你设置了变量的值,就没有办法改变它,即使是在case子句这样的模式匹配中也不行。要做你想做的,只要删除case表达式前面将变量设置为undefined的行。这样,变量在匹配过程中就被赋值了。

相关问题