スタンドアロンモードには、主に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.