1. Análisis del código fuente del módulo emqx_backend_mysql_cli
-module(emqx_backend_mysql_cli).
-include("emqx/include/emqx.hrl").
%% 导出接口函数
-export([client_connected/2,
subscribe_lookup/2,
client_disconnected/2,
message_fetch/3,
lookup_retain/2,
message_publish/2,
message_store/2,
message_retain/2,
delete_retain/2,
message_acked/2,
run_mysql_sql/3]).
-export([record_to_msg/1]).
-export([connect/1, send_batch/2]).
%% 已经连接的客户端
client_connected(Pool, Msg) ->
mysql_execute(Pool, client_connected_query,
[proplists:get_value(clientid, Msg),
1,
atom_to_list(node()),
1,
atom_to_list(node())]),
ok.
%% 订阅查找配置
subscribe_lookup(Pool, Msg) ->
case mysql_execute(Pool,subscribe_lookup_query,feed_var([<<"${clientid}">>], Msg)) of
%% 空
{ok, _Cols, []} -> [];
%% 错误
{error, Error} ->
logger:error("Lookup retain error: ~p", [Error]),
[];
%% 返回数据
{ok, _Cols, Rows} ->
%% 从返回的行数总,提取Topic和qos,组成列表
[{Topic, #{qos => Qos}} || [Topic, Qos] <- Rows]
end.
%% 查询已经断开客户端
client_disconnected(Pool, Msg) ->
mysql_execute(Pool,client_disconnected_query,
[0, proplists:get_value(clientid, Msg)]),
ok.
%% 消息
message_fetch(Pool, Msg, Opts) ->
%% 获取配置的主题
Topic = proplists:get_value(topic, Msg),
%% 获取客户端ID
ClientId = proplists:get_value(clientid, Msg),
%% 执行查询
case mysql_execute(Pool,message_fetch_query,
feed_var([<<"${topic}">>, <<"${clientid}">>], Msg)) of
{ok, [_], []} ->
%% 查询Topic最新的message数据
MsgId = case mysql_execute(Pool,message_lastid_query, [Topic]) of
{ok, [_], []} -> 0;
{ok, [_], [[MId]]} -> MId;
{error, Error2} ->
logger:error("Lookup msg error: ~p", [Error2]),
0
end,
%% 查询插入的消息回馈
mysql_execute(Pool,insert_acked_query, [ClientId, Topic, MsgId]),
[];
{ok, [_], [[AckId]]} ->
%% 构造sql查询语句
Sql = <<"select id, topic, msgid, sender, qos, "
"payload, retain, UNIX_TIMESTAMP(arrived) "
"as arrived from mqtt_msg where id > "
"? and topic = ? ">>,
{Sql1, Params1} = case proplists:get_value(time_range,Opts) of
undefined ->
{<<" order by id DESC ">>,
[AckId, Topic]};
TimeRange ->
Time = erlang:system_time(seconds) -TimeRange,
{<<" and arrived >= FROM_UNIXTIME(?) order "
"by id DESC ">>,
[AckId, Topic, Time]}
end,
{Sql2, Params2} = case
proplists:get_value(max_returned_count, Opts)
of
undefined -> {<<"">>, Params1};
MaxReturnedCount ->
{<<" limit ?">>,
Params1 ++ [MaxReturnedCount]}
end,
%% 执行查询
case mysql_query(Pool,<<Sql/binary, Sql1/binary, Sql2/binary>>, Params2) of
{ok, _Cols, []} -> [];
{ok, Cols, Rows} ->
[begin
M = record_to_msg(lists:zip(Cols, Row)),
M#message{id = emqx_guid:from_base62(M#message.id)}
end || Row <- lists:reverse(Rows)];
{error, Error1} ->
logger:error("Lookup msg error: ~p", [Error1]),
[]
end;
{error, Error} ->
logger:error("Lookup msg error: ~p", [Error]),
[]
end.