25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Improve purge_offline filter and speed (#543)

This commit is contained in:
Christophe Romain 2015-04-22 18:11:39 +02:00
parent df3afafb48
commit 38dd44e18f

View File

@ -4268,63 +4268,78 @@ on_user_offline(_, JID, _) ->
_ -> true
end.
purge_offline({User, Server, _} = LJID) ->
purge_offline(LJID) ->
Host = host(element(2, LJID)),
Plugins = plugins(Host),
Result = lists:foldl(fun (Type, {Status, Acc}) ->
Features = plugin_features(Host, Type),
case lists:member(<<"retrieve-affiliations">>, plugin_features(Host, Type)) of
false ->
{{error,
extended_error(?ERR_FEATURE_NOT_IMPLEMENTED,
{{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED,
unsupported, <<"retrieve-affiliations">>)},
Acc};
true ->
{result, Affs} = node_action(Host, Type,
get_entity_affiliations,
[Host, LJID]),
{Status, [Affs | Acc]}
Items = lists:member(<<"retract-items">>, Features)
andalso lists:member(<<"persistent-items">>, Features),
if Items ->
{result, Affs} = node_action(Host, Type,
get_entity_affiliations, [Host, LJID]),
{Status, [Affs | Acc]};
true ->
{Status, Acc}
end
end
end,
{ok, []}, Plugins),
case Result of
{ok, Affs} ->
lists:foreach(
fun ({Node, Affiliation}) ->
Options = Node#pubsub_node.options,
Publisher = lists:member(Affiliation, [owner,publisher,publish_only]),
Open = (get_option(Options, publish_model) == open),
Purge = (get_option(Options, purge_offline)
andalso get_option(Options, persist_items)),
if (Publisher or Open) and Purge ->
purge_offline(Host, LJID, Node);
true ->
ok
end
end, lists:usort(lists:flatten(Affs)));
{Error, _} ->
?DEBUG("on_user_offline ~p", [Error])
end.
purge_offline(Host, LJID, Node) ->
Nidx = Node#pubsub_node.id,
Type = Node#pubsub_node.type,
Options = Node#pubsub_node.options,
case node_action(Host, Type, get_items, [Nidx, service_jid(Host), none]) of
{result, {[], _}} ->
ok;
{result, {Items, _}} ->
{User, Server, _} = LJID,
PublishModel = get_option(Options, publish_model),
ForceNotify = get_option(Options, notify_retract),
{_, NodeId} = Node#pubsub_node.nodeid,
lists:foreach(fun
({#pubsub_node{nodeid = {_, Node}, options = Options, type = Type}, Aff})
when Aff == owner orelse Aff == publisher ->
Action = fun (#pubsub_node{type = NType, id = Nidx}) ->
node_call(Host, NType, get_items, [Nidx, service_jid(Host), none])
end,
case transaction(Host, Node, Action, sync_dirty) of
{result, {_, {[], _}}} ->
true;
{result, {_, {Items, _}}} ->
Features = plugin_features(Host, Type),
case {lists:member(<<"retract-items">>, Features),
lists:member(<<"persistent-items">>, Features),
get_option(Options, persist_items),
get_option(Options, purge_offline)}
of
{true, true, true, true} ->
ForceNotify = get_option(Options, notify_retract),
lists:foreach(fun
(#pubsub_item{itemid = {ItemId, _},
modification = {_, {U, S, _}}})
when (U == User) and (S == Server) ->
delete_item(Host, Node, LJID, ItemId, ForceNotify);
(_) ->
true
end,
Items);
_ ->
true
(#pubsub_item{itemid = {ItemId, _}, modification = {_, {U, S, _}}})
when (U == User) and (S == Server) ->
case node_action(Host, Type, delete_item, [Nidx, {U, S, <<>>}, PublishModel, ItemId]) of
{result, {_, broadcast}} ->
broadcast_retract_items(Host, NodeId, Nidx, Type, Options, [ItemId], ForceNotify),
case get_cached_item(Host, Nidx) of
#pubsub_item{itemid = {ItemId, Nidx}} -> unset_cached_item(Host, Nidx);
_ -> ok
end;
{result, _} ->
ok;
Error ->
Error
end;
(_) ->
true
end,
lists:usort(lists:flatten(Affs)));
{Error, _} ->
?DEBUG("on_user_offline ~p", [Error])
end, Items);
Error ->
Error
end.