Я использую ejabberd-17.03 из исходного кода на Linux-машине.
Я программно создал временный чат с сервера, используя jid пользователя A, и отправил прямое приглашение пользователю B, которое он принял, и присоединился к чату.
Мой вариант использования заключается в том, что два пользователя A и B находятся в чате и обмениваются сообщениями. Если ни один пользователь не отправляет другому пользователю какое-либо сообщение в течение 30 секунд, комната отправляет случайно выбранное сообщение этим двум пользователям.
Я реализовал это следующим образом:
start(_Host, _Opts) ->
ejabberd_hooks:add(user_send_packet, _Host, ?MODULE, myMessage, 95).
stop(_Host) ->
ejabberd_hooks:delete(user_send_packet, _Host, ?MODULE, myMessage,95).
depends(_Host, _Opts)->[{?MODULE,soft}].
mod_opt_type(_Option)->
ok.
myMessage({#message{from = From, to = To, body= Body} =Packet, C2SState}) ->
{UserA,UserB}=select_user(Packet),
PacketType=returnPacketType(Packet),
if
(PacketType==normal) ->
dosomething(),
{Timer_Result,Ref_or_Reason} = timer:apply_interval(30000, ?MODULE, func(), [Arguments]),
if
(Timer_Result == ok)->
ets:insert(ref_table, {Key, Ref_or_Reason});
(Timer_Result == error)->
io:format(" Could not delete user after timeout, Reason is ~p~n",[Ref_or_Reason])
end;
(PacketType==groupchat)->
do_something_else(),
{Timer_Result,Ref_or_Reason} = timer:apply_interval(30000, ?MODULE, func(), [Arguments]),
if
(Timer_Result == ok)->
replace_old_ref_with_new(Key, Ref_or_Reason, ref_table);
(Timer_Result == error)->
io:format(" Could not delete user after timeout, Reason is ~p~n",[Ref_or_Reason])
end
end
if
(somecondition()==true)->
delete_ref(Key, ref_table);
True->
do_nothing
end,
{Packet, C2SState}.
Теперь все работает нормально, за исключением следующего случая:
1. Создается чат, и начинается обмен сообщениями между A и B, и в этот момент также запускается таймер.
Если пользователь, создавший чат, уходит в автономный режим, скажем, в момент времени T (сворачивая приложение и удаляя его с устройства Android) и возвращается в сеть, таймер останавливается, как в запланированной функции. в конце 30 секунд не вызывается. (здесь возвращается в сеть выделено, потому что, если пользователь не подключается к сети, таймер работает должным образом, только когда пользователь снова подключается к сети, таймер останавливается и нет журналов генерируются).
Но если онлайн-пользователь отправляет какое-либо сообщение сейчас в этот момент в T, то вся периодическая операция по случайному выбору сообщений и их отправке клиентам начинается снова довольно хорошо и заканчивается хорошо.
Но если онлайн-пользователь не отправляет никаких сообщений в этот момент времени T, то запланированный таймер никогда не вызывается, и пользователь продолжает ждать.
Если пользователь, которого пригласили в чат, выходит из сети в момент времени T2 (скажем, как в случае 2) и снова подключается к сети, то таймер остается активным и работает как положено.
Поэтому я изменил уровень ведения журнала ejabberd на 5 и увидел, что офлайн-сообщения офлайн-пользователю и снова онлайн-пользователю не доставляются, даже несмотря на то, что mod_offline включен в ejabberd.yml.
Журнал :
#message{
id = <<>>,type = error,lang = <<"en">>,
from =
{jid,<<"fWiTvj973AB”>>,<<“example.com">>,<<"Smack">>,<<"fwitvj973ab”>>,
<<"example.com">>,<<"Smack">>},
to =
{jid,<<"ac5a6b8c-66b8-4da7-8b1a-0f3ecb1e5gfd”>>,
<<"conference.example.com">>,<<"cXWmOrqEESd”>>,
<<"ac5a6b8c-66b8-4da7-8b1a-0f3ecb1e5gfd">>,
<<"conference.example.com">>,<<"cXWmOrqEESd">>},
subject = [#text{lang = <<>>,data = <<>>}],
body = [#text{lang = <<>>,data = <<"\"cXWmOrqEESd\"">>}],
thread = undefined,
sub_els =
[{xmlel,<<"q">>,[{<<"xmlns">>,<<"ns:custom”>>}],[]},
#stanza_error{
type = cancel,code = 503,by = <<>>,
reason = 'service-unavailable',
text =
#text{lang = <<"en">>,data = <<"User session terminated">>},
sub_els = []}],
meta = #{}}
ejabberd.yml
###. ============
###' SHAPER RULES
shaper_rules:
## Maximum number of offline messages that users can have:
max_user_offline_messages:
- 5000: admin
- 100
###. =======
###' MODULES
##
## Modules enabled in all ejabberd virtual hosts.
##
modules:
mod_offline:
db_type: sql
access_max_user_messages: max_user_offline_messages
store_empty_body: unless_chat_state
Хотя мне не нужно, чтобы эти автономные сообщения доставлялись идеально, но я склоняюсь к мысли, что может ли это быть причиной остановки моего таймера (но я не могу понять, почему он останавливается только тогда, когда пользователь, создавший комната отключается и возвращается, а почему бы и нет, когда это делает другой пользователь?).
Почему этот таймер останавливается и как я могу периодически запускать его?