如何接收发送到在 gen_server 内运行的 PID 的消息

问题描述

  • 我有一个 ejabberd 服务器

  • 我有一个自定义模块 my_apns_module.erl,它由 ejabberd 服务器运行,如下所示:

    start_link(Host,Opts) ->
      Proc = gen_mod:get_module_proc(Host,?PROCNAME),?GEN_SERVER:start_link({local,Proc},?MODULE,[Host,Opts],[]).
    start(Host,ChildSpec = {Proc,{?MODULE,start_link,Opts]},temporary,1000,worker,[?MODULE]},supervisor:start_child(ejabberd_sup,ChildSpec).
    
    stop(Host) ->
      Proc = gen_mod:get_module_proc(Host,?GEN_SERVER:call(Proc,stop),supervisor:delete_child(ejabberd_sup,Proc),ok.
    
    init([Host,_Opts]) ->
       ...
    
    handle_call(stop,_From,State) ->
      {stop,normal,ok,State}.
    
    handle_cast(_Msg,State) -> {noreply,State}.
    
    handle_info(#offline_msg{us = _UserServer,from = From,to = To,packet = Packet} = _Msg,State) ->
      ...
    
    handle_info(_Info,State) ->
      {noreply,State}.
    
    terminate(_Reason,State) ->
      Host = State#state.host,ok.
    
    code_change(_OldVsn,State,_Extra) -> {ok,State}.
    
  • 在 init 中,我运行另一个 APNs 应用程序来发送推送通知https://github.com/inaka/apns4erl

    init([Host,_Opts]) ->
          apns:start(),case apns:connect(cert,?APNS_CONNECTION) of
               {ok,PID} -> ?INFO_MSG("apns connection successful with PID ~p~n",[PID]);
               {error,timeout} -> ?ERROR_MSG("apns connection unsuccessful reason timed out",[])
          end,{ok,#state{host = Host}}.
    
  • 这是有效的,因为我可以发送通知

  • 现在文档 (https://github.com/inaka/apns4erl) 说:

如果网络出现故障或发生意外情况,枪 与 APNs 的连接将会中断。在这种情况下 apns4erl 将发送一个 向客户端进程发送消息 {reconnecting,ServerPid},这意味着 apns4erl 失去了连接,它正在尝试重新连接。一旦 连接已恢复,{connection_up,ServerPid} 消息将 发送。

我的问题是:

  • 我应该在 my_apns_module.erl 中编写什么代码来接收 {reconnecting,ServerPid}{connection_up,ServerPid}

解决方法

发送到 gen_server 进程的消息,例如GenServerPid ! {ok,10}},由以下人员处理:

handle_info(Msg,State)

所以,你可以这样做:

handle_info({reconnecting,ServerPid}=Msg,State) ->
     %%do something here,like log Msg or change State;
handl_info({connection_up,like log Msg or change State;   
handle_info(#offline_msg{us = _UserServer,from = From,to = To,packet = Packet} = _Msg,State) ->
     %%do something.

回复评论:

这是您当前的代码:

init([Host,_Opts]) ->
      apns:start(),case apns:connect(cert,?APNS_CONNECTION) of
           {ok,PID} -> ?INFO_MSG("apns connection successful with PID ~p~n",[PID]);
           {error,timeout} -> ?ERROR_MSG("apns connection unsuccessful reason timed out",[])
      end,{ok,#state{host = Host}}.

你可以把它改成这样:

init([Host,_Opts]) ->
    spawn(?MODULE,start_apns,[]),...


start_apns() ->

          apns:start(),?APNS_CONNECTION) of
               {ok,[PID]);
               {error,[])
          end,apns_loop().

apns_loop() ->
    receive
        {reconnecting,ServerPid} -> %%do something;
        {connection_up,ServerPid} -> %% do something;
        Other -> %% do something
    end,apns_loop().
  

启动apns进程后,apns进程会进入一个循环,等待消息。