EMQXメッセージストレージRedisソースコード分析(5)

スタンドアロンモードには、主にredisデータのサブスクライブに使用されるemqx_backend_redis_subモジュールが含まれます。

-module(emqx_backend_redis_sub).
-behaviour(gen_server).

-export([start_link/1]).

-export([init/1,handle_call/3,handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {sub}).

start_link(Opts) ->
  gen_server:start_link(emqx_backend_redis_sub, [Opts], []).

init([Opts]) ->
  %% 获取配置通道
  Channel = proplists:get_value(channel, Opts),
  %% 流量防卫模式
  Sentinel = proplists:get_value(sentinel, Opts),
  %% 主机地址
  Host = case Sentinel =:= "" of
           true -> proplists:get_value(host, Opts);
           false ->
             eredis_sentinel:start_link(proplists:get_value(servers, Opts)),
             "sentinel:" ++ Sentinel
         end,
  %% 启动连接redis,返回Sub
  {ok, Sub} = eredis:start_link(Host, proplists:get_value(port, Opts), 
  %% 获取redis配置
  proplists:get_value(database, Opts), proplists:get_value(password, Opts)),
  %% 转交进程处理到Sub
  eredis_sub:controlling_process(Sub, self()),
  %% 订阅通道
  eredis_sub:subscribe(Sub, [list_to_binary(Channel)]),
  {ok, #state{sub = Sub}}.

handle_call(_Req, _From, State) ->
  {reply, ignore, State}.

handle_cast(_Msg, State) -> {noreply, State}.

%% 处理订阅
handle_info({subscribed, Channel, Sub}, State) ->
  logger:debug("recv subscribed:~p", [Channel]),
  eredis_sub:ack_message(Sub),
  {noreply, State};

handle_info({message, Channel, Msg, Sub}, State) ->
  logger:debug("recv channel:~p, msg:~p", [Channel, Msg]),
  eredis_sub:ack_message(Sub),
  %% 解码消息
  try Params = emqx_json:decode(Msg),
  %% 获取消息类型
  Type = proplists:get_value(<<"type">>, Params),
  %% 获取消息主题
  Topic1 = proplists:get_value(<<"topic">>, Params),
  %% 获取消息客户端ID
  ClientId = proplists:get_value(<<"clientid">>, Params),
%%    查询客户端的进程id
  ClientPid = emqx_cm:lookup_proc(ClientId),
%%  判读是订阅类型 或者 取消订阅
  case Type of
     %% 订阅
    <<"subscribe">> ->
      %% 查询消息质量
      Qos = proplists:get_value(<<"qos">>, Params),
      %% 订阅进程的主题
      emqx_client:subscribe(ClientPid, [{Topic1, to_int(Qos)}]);
    //取消订阅
    <<"unsubscribe">> ->
      emqx_client:unsubscribe(ClientPid, [Topic1])
  end
  catch
    _:Error:Stack ->
      logger:error("decode json error:~p,~p", [Error, Stack])
  end,
  {noreply, State}.

terminate(_Reason, #state{}) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

to_int(undefined) -> 0;
to_int(B) when is_binary(B) -> binary_to_integer(B);
to_int(S) when is_list(S) -> list_to_integer(S);
to_int(I) when is_integer(I) -> I.

 

おすすめ

転載: blog.csdn.net/qq513036862/article/details/112954324