From b6671489825140af9c7099c77b898a4b35c2d265 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 13 Oct 2009 16:43:02 +0000 Subject: [PATCH] prevent remove_user from blocking gen_server, and allow plugin to change broadcasted payload on publish SVN Revision: 2666 --- src/mod_pubsub/mod_pubsub.erl | 98 +++++++++++++------------ src/mod_pubsub/mod_pubsub_odbc.erl | 98 +++++++++++++------------ src/mod_pubsub/pubsub_odbc.patch | 114 ++++++++++++++--------------- 3 files changed, 161 insertions(+), 149 deletions(-) diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 205a3fd11..a449644f8 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -42,9 +42,6 @@ %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% XEP-0060 section 12.18. -%%% TODO -%%% plugin: generate Reply (do not use broadcast atom anymore) - -module(mod_pubsub). -author('christophe.romain@process-one.net'). -version('1.13-0'). @@ -780,50 +777,54 @@ handle_cast({presence, User, Server, Resources, JID}, State) -> {noreply, send_queue(State, {presence, User, Server, Resources, JID})}; handle_cast({remove_user, LUser, LServer}, State) -> - Host = State#state.host, - Owner = jlib:make_jid(LUser, LServer, ""), - %% remove user's subscriptions - lists:foreach(fun(PType) -> - {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), - lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}}, subscribed, _, JID}) -> - unsubscribe_node(H, N, Owner, JID, all); - (_) -> - ok - end, Subscriptions), - {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Owner]), - lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}}, owner}) -> - delete_node(H, N, Owner); - (_) -> - ok - end, Affiliations) - end, State#state.plugins), + spawn(fun() -> + Host = State#state.host, + Owner = jlib:make_jid(LUser, LServer, ""), + %% remove user's subscriptions + lists:foreach(fun(PType) -> + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}}, subscribed, _, JID}) -> + unsubscribe_node(H, N, Owner, JID, all); + (_) -> + ok + end, Subscriptions), + {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Owner]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}}, owner}) -> + delete_node(H, N, Owner); + (_) -> + ok + end, Affiliations) + end, State#state.plugins) + end), {noreply, State}; handle_cast({unsubscribe, Subscriber, Owner}, State) -> - Host = State#state.host, - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - lists:foreach(fun(PType) -> - {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), - lists:foreach(fun - ({Node, subscribed, _, JID}) -> - #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node, - case get_option(Options, access_model) of - presence -> - case lists:member(BJID, Owners) of - true -> - node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); - false -> - {result, ok} - end; - _ -> - {result, ok} - end; - (_) -> - ok - end, Subscriptions) - end, State#state.plugins), + spawn(fun() -> + Host = State#state.host, + BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + lists:foreach(fun(PType) -> + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), + lists:foreach(fun + ({Node, subscribed, _, JID}) -> + #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node, + case get_option(Options, access_model) of + presence -> + case lists:member(BJID, Owners) of + true -> + node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); + false -> + {result, ok} + end; + _ -> + {result, ok} + end; + (_) -> + ok + end, Subscriptions) + end, State#state.plugins) + end), {noreply, State}; handle_cast(_Msg, State) -> @@ -2021,11 +2022,16 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> [{xmlelement, "publish", nodeAttr(Node), [{xmlelement, "item", itemAttr(ItemId), []}]}]}], case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast, Removed}}} -> + {result, {TNode, {Result, Broadcast, Removed}}} -> NodeId = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:jid_tolower(Publisher), Payload), + BroadcastPayload = case Broadcast of + default -> Payload; + broadcast -> Payload; + PluginPayload -> PluginPayload + end, + broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:jid_tolower(Publisher), BroadcastPayload), set_cached_item(Host, NodeId, ItemId, Payload), case Result of default -> {result, Reply}; diff --git a/src/mod_pubsub/mod_pubsub_odbc.erl b/src/mod_pubsub/mod_pubsub_odbc.erl index cd6933015..ff06097f1 100644 --- a/src/mod_pubsub/mod_pubsub_odbc.erl +++ b/src/mod_pubsub/mod_pubsub_odbc.erl @@ -42,9 +42,6 @@ %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% XEP-0060 section 12.18. -%%% TODO -%%% plugin: generate Reply (do not use broadcast atom anymore) - -module(mod_pubsub_odbc). -author('christophe.romain@process-one.net'). -version('1.13-0'). @@ -604,50 +601,54 @@ handle_cast({presence, User, Server, Resources, JID}, State) -> {noreply, send_queue(State, {presence, User, Server, Resources, JID})}; handle_cast({remove_user, LUser, LServer}, State) -> - Host = State#state.host, - Owner = jlib:make_jid(LUser, LServer, ""), - %% remove user's subscriptions - lists:foreach(fun(PType) -> - {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), - lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}}, subscribed, _, JID}) -> - unsubscribe_node(H, N, Owner, JID, all); - (_) -> - ok - end, Subscriptions), - {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Owner]), - lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}}, owner}) -> - delete_node(H, N, Owner); - (_) -> - ok - end, Affiliations) - end, State#state.plugins), + spawn(fun() -> + Host = State#state.host, + Owner = jlib:make_jid(LUser, LServer, ""), + %% remove user's subscriptions + lists:foreach(fun(PType) -> + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Owner]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}}, subscribed, _, JID}) -> + unsubscribe_node(H, N, Owner, JID, all); + (_) -> + ok + end, Subscriptions), + {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Owner]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}}, owner}) -> + delete_node(H, N, Owner); + (_) -> + ok + end, Affiliations) + end, State#state.plugins) + end), {noreply, State}; handle_cast({unsubscribe, Subscriber, Owner}, State) -> - Host = State#state.host, - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - lists:foreach(fun(PType) -> - {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), - lists:foreach(fun - ({Node, subscribed, _, JID}) -> - #pubsub_node{options = Options, type = Type, id = NodeId} = Node, - case get_option(Options, access_model) of - presence -> - case lists:member(BJID, node_owners(Host, Type, NodeId)) of - true -> - node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); - false -> - {result, ok} - end; - _ -> - {result, ok} - end; - (_) -> - ok - end, Subscriptions) - end, State#state.plugins), + spawn(fun() -> + Host = State#state.host, + BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + lists:foreach(fun(PType) -> + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), + lists:foreach(fun + ({Node, subscribed, _, JID}) -> + #pubsub_node{options = Options, type = Type, id = NodeId} = Node, + case get_option(Options, access_model) of + presence -> + case lists:member(BJID, node_owners(Host, Type, NodeId)) of + true -> + node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); + false -> + {result, ok} + end; + _ -> + {result, ok} + end; + (_) -> + ok + end, Subscriptions) + end, State#state.plugins) + end), {noreply, State}; handle_cast(_Msg, State) -> @@ -1856,11 +1857,16 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> [{xmlelement, "publish", nodeAttr(Node), [{xmlelement, "item", itemAttr(ItemId), []}]}]}], case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast, Removed}}} -> + {result, {TNode, {Result, Broadcast, Removed}}} -> NodeId = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:jid_tolower(Publisher), Payload), + BroadcastPayload = case Broadcast of + default -> Payload; + broadcast -> Payload; + PluginPayload -> PluginPayload + end, + broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:jid_tolower(Publisher), BroadcastPayload), set_cached_item(Host, NodeId, ItemId, Payload), case Result of default -> {result, Reply}; diff --git a/src/mod_pubsub/pubsub_odbc.patch b/src/mod_pubsub/pubsub_odbc.patch index 80108a270..99c0a7809 100644 --- a/src/mod_pubsub/pubsub_odbc.patch +++ b/src/mod_pubsub/pubsub_odbc.patch @@ -1,15 +1,15 @@ ---- mod_pubsub.erl 2009-10-12 11:57:04.000000000 +0200 -+++ mod_pubsub_odbc.erl 2009-10-12 11:57:19.000000000 +0200 -@@ -45,7 +45,7 @@ - %%% TODO - %%% plugin: generate Reply (do not use broadcast atom anymore) +--- mod_pubsub.erl 2009-10-13 18:30:32.000000000 +0200 ++++ mod_pubsub_odbc.erl 2009-10-13 18:30:47.000000000 +0200 +@@ -42,7 +42,7 @@ + %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see + %%% XEP-0060 section 12.18. --module(mod_pubsub). +-module(mod_pubsub_odbc). -author('christophe.romain@process-one.net'). -version('1.13-0'). -@@ -57,9 +57,9 @@ +@@ -54,9 +54,9 @@ -include("jlib.hrl"). -include("pubsub.hrl"). @@ -22,7 +22,7 @@ %% exports for hooks -export([presence_probe/3, -@@ -105,7 +105,7 @@ +@@ -102,7 +102,7 @@ string_to_affiliation/1, extended_error/2, extended_error/3, @@ -31,7 +31,7 @@ ]). %% API and gen_server callbacks -@@ -124,7 +124,7 @@ +@@ -121,7 +121,7 @@ -export([send_loop/1 ]). @@ -40,7 +40,7 @@ -define(PLUGIN_PREFIX, "node_"). -define(TREE_PREFIX, "nodetree_"). -@@ -218,8 +218,6 @@ +@@ -215,8 +215,6 @@ ok end, ejabberd_router:register_route(Host), @@ -49,7 +49,7 @@ init_nodes(Host, ServerHost, NodeTree, Plugins), State = #state{host = Host, server_host = ServerHost, -@@ -280,178 +278,6 @@ +@@ -277,178 +275,6 @@ ok end. @@ -228,7 +228,7 @@ send_queue(State, Msg) -> Pid = State#state.send_loop, case is_process_alive(Pid) of -@@ -474,17 +300,15 @@ +@@ -471,17 +297,15 @@ %% for each node From is subscribed to %% and if the node is so configured, send the last published item to From lists:foreach(fun(PType) -> @@ -253,19 +253,19 @@ % resource not concerned about that subscription ok @@ -808,10 +632,10 @@ - {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), - lists:foreach(fun - ({Node, subscribed, _, JID}) -> -- #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node, -+ #pubsub_node{options = Options, type = Type, id = NodeId} = Node, - case get_option(Options, access_model) of - presence -> -- case lists:member(BJID, Owners) of -+ case lists:member(BJID, node_owners(Host, Type, NodeId)) of - true -> - node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); - false -> -@@ -925,7 +749,8 @@ + {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Subscriber]), + lists:foreach(fun + ({Node, subscribed, _, JID}) -> +- #pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId} = Node, ++ #pubsub_node{options = Options, type = Type, id = NodeId} = Node, + case get_option(Options, access_model) of + presence -> +- case lists:member(BJID, Owners) of ++ case lists:member(BJID, node_owners(Host, Type, NodeId)) of + true -> + node_action(Host, Type, unsubscribe_node, [NodeId, Subscriber, JID, all]); + false -> +@@ -926,7 +750,8 @@ sub_el = SubEl} = IQ -> {xmlelement, _, QAttrs, _} = SubEl, Node = xml:get_attr_s("node", QAttrs), @@ -275,7 +275,7 @@ {result, IQRes} -> jlib:iq_to_xml( IQ#iq{type = result, -@@ -1030,7 +855,7 @@ +@@ -1031,7 +856,7 @@ [] -> ["leaf"]; %% No sub-nodes: it's a leaf node _ -> @@ -284,7 +284,7 @@ {result, []} -> ["collection"]; {result, _} -> ["leaf", "collection"]; _ -> [] -@@ -1046,8 +871,9 @@ +@@ -1047,8 +872,9 @@ []; true -> [{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []} | @@ -296,7 +296,7 @@ end, features(Type))] end, %% TODO: add meta-data info (spec section 5.4) -@@ -1075,14 +901,15 @@ +@@ -1076,14 +902,15 @@ {xmlelement, "feature", [{"var", ?NS_DISCO_ITEMS}], []}, {xmlelement, "feature", [{"var", ?NS_PUBSUB}], []}, {xmlelement, "feature", [{"var", ?NS_VCARD}], []}] ++ @@ -315,7 +315,7 @@ {result, lists:map( fun(#pubsub_node{nodeid = {_, SubNode}}) -> SN = node_to_string(SubNode), -@@ -1092,7 +919,7 @@ +@@ -1093,7 +920,7 @@ {"node", SN}, {"name", RN}], []} end, tree_action(Host, get_subnodes, [Host, [], From]))}; @@ -324,7 +324,7 @@ case string:tokens(Item, "!") of [_SNode, _ItemID] -> {result, []}; -@@ -1104,10 +931,10 @@ +@@ -1105,10 +932,10 @@ %% TODO That is, remove name attribute (or node?, please check for 2.1) Action = fun(#pubsub_node{type = Type, id = NodeId}) -> @@ -338,7 +338,7 @@ end, Nodes = lists:map( fun(#pubsub_node{nodeid = {_, SubNode}}) -> -@@ -1123,7 +950,7 @@ +@@ -1124,7 +951,7 @@ {xmlelement, "item", [{"jid", Host}, {"node", SN}, {"name", Name}], []} end, NodeItems), @@ -347,7 +347,7 @@ end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> {result, Result}; -@@ -1255,7 +1082,8 @@ +@@ -1256,7 +1083,8 @@ (_, Acc) -> Acc end, [], xml:remove_cdata(Els)), @@ -357,7 +357,7 @@ {get, "subscriptions"} -> get_subscriptions(Host, Node, From, Plugins); {get, "affiliations"} -> -@@ -1278,7 +1106,9 @@ +@@ -1279,7 +1107,9 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> {xmlelement, _, _, SubEls} = SubEl, @@ -368,7 +368,7 @@ case Action of [{xmlelement, Name, Attrs, Els}] -> Node = case Host of -@@ -1404,7 +1234,8 @@ +@@ -1405,7 +1235,8 @@ _ -> [] end end, @@ -378,7 +378,7 @@ sync_dirty) of {result, Res} -> Res; Err -> Err -@@ -1444,7 +1275,7 @@ +@@ -1445,7 +1276,7 @@ %%% authorization handling @@ -387,7 +387,7 @@ Lang = "en", %% TODO fix Stanza = {xmlelement, "message", [], -@@ -1473,7 +1304,7 @@ +@@ -1474,7 +1305,7 @@ [{xmlelement, "value", [], [{xmlcdata, "false"}]}]}]}]}, lists:foreach(fun(Owner) -> ejabberd_router ! {route, service_jid(Host), jlib:make_jid(Owner), Stanza} @@ -396,7 +396,7 @@ find_authorization_response(Packet) -> {xmlelement, _Name, _Attrs, Els} = Packet, -@@ -1540,8 +1371,8 @@ +@@ -1541,8 +1372,8 @@ "true" -> true; _ -> false end, @@ -407,7 +407,7 @@ {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), if not IsApprover -> -@@ -1727,7 +1558,7 @@ +@@ -1728,7 +1559,7 @@ Reply = [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [{xmlelement, "create", nodeAttr(Node), []}]}], @@ -416,7 +416,7 @@ {result, {Result, broadcast}} -> %%Lang = "en", %% TODO: fix %%OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), -@@ -1835,7 +1666,7 @@ +@@ -1836,7 +1667,7 @@ %%
  • The node does not exist.
  • %% subscribe_node(Host, Node, From, JID, Configuration) -> @@ -425,7 +425,7 @@ {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, -@@ -1843,7 +1674,7 @@ +@@ -1844,7 +1675,7 @@ error -> {"", "", ""}; J -> jlib:jid_tolower(J) end, @@ -434,7 +434,7 @@ Features = features(Type), SubscribeFeature = lists:member("subscribe", Features), OptionsFeature = lists:member("subscription-options", Features), -@@ -1862,9 +1693,13 @@ +@@ -1863,9 +1694,13 @@ {"", "", ""} -> {false, false}; _ -> @@ -451,7 +451,7 @@ end end, if -@@ -2190,7 +2025,7 @@ +@@ -2196,7 +2031,7 @@ %%

    The permission are not checked in this function.

    %% @todo We probably need to check that the user doing the query has the right %% to read the items. @@ -460,7 +460,7 @@ MaxItems = if SMaxItems == "" -> get_max_items_node(Host); -@@ -2229,11 +2064,11 @@ +@@ -2235,11 +2070,11 @@ node_call(Type, get_items, [NodeId, From, AccessModel, PresenceSubscription, RosterGroup, @@ -474,7 +474,7 @@ SendItems = case ItemIDs of [] -> Items; -@@ -2246,7 +2081,8 @@ +@@ -2252,7 +2087,8 @@ %% number of items sent to MaxItems: {result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}], [{xmlelement, "items", nodeAttr(Node), @@ -484,7 +484,7 @@ Error -> Error end -@@ -2278,16 +2114,27 @@ +@@ -2284,16 +2120,27 @@ %% @doc

    Resend the items of a node to the user.

    %% @todo use cache-last-item feature send_items(Host, Node, NodeId, Type, LJID, last) -> @@ -518,7 +518,7 @@ send_items(Host, Node, NodeId, Type, LJID, Number) -> ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of {result, []} -> -@@ -2413,29 +2260,12 @@ +@@ -2419,29 +2266,12 @@ error -> {error, ?ERR_BAD_REQUEST}; _ -> @@ -551,7 +551,7 @@ end, Entities), {result, []}; _ -> -@@ -2488,11 +2318,11 @@ +@@ -2494,11 +2324,11 @@ end. read_sub(Subscriber, Node, NodeID, SubID, Lang) -> @@ -565,7 +565,7 @@ OptionsEl = {xmlelement, "options", [{"node", node_to_string(Node)}, {"jid", jlib:jid_to_string(Subscriber)}, {"subid", SubID}], -@@ -2519,7 +2349,7 @@ +@@ -2525,7 +2355,7 @@ end. set_options_helper(Configuration, JID, NodeID, SubID, Type) -> @@ -574,7 +574,7 @@ {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, -@@ -2548,7 +2378,7 @@ +@@ -2554,7 +2384,7 @@ write_sub(_Subscriber, _NodeID, _SubID, invalid) -> {error, extended_error(?ERR_BAD_REQUEST, "invalid-options")}; write_sub(Subscriber, NodeID, SubID, Options) -> @@ -583,7 +583,7 @@ {error, notfound} -> {error, extended_error(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; {result, _} -> -@@ -2716,8 +2546,8 @@ +@@ -2722,8 +2552,8 @@ {"subscription", subscription_to_string(Sub)} | nodeAttr(Node)], []}]}]}, ejabberd_router ! {route, service_jid(Host), jlib:make_jid(JID), Stanza} end, @@ -594,7 +594,7 @@ true -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> -@@ -3007,7 +2837,7 @@ +@@ -3013,7 +2843,7 @@ {Depth, [{N, get_node_subs(N)} || N <- Nodes]} end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} end, @@ -603,7 +603,7 @@ {result, CollSubs} -> CollSubs; _ -> [] end. -@@ -3021,9 +2851,9 @@ +@@ -3027,9 +2857,9 @@ get_options_for_subs(NodeID, Subs) -> lists:foldl(fun({JID, subscribed, SubID}, Acc) -> @@ -615,7 +615,7 @@ _ -> Acc end; (_, Acc) -> -@@ -3221,6 +3051,30 @@ +@@ -3227,6 +3057,30 @@ Result end. @@ -646,7 +646,7 @@ %% @spec (Host, Options) -> MaxItems %% Host = host() %% Options = [Option] -@@ -3607,7 +3461,13 @@ +@@ -3613,7 +3467,13 @@ tree_action(Host, Function, Args) -> ?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]), Fun = fun() -> tree_call(Host, Function, Args) end, @@ -661,7 +661,7 @@ %% @doc

    node plugin call.

    node_call(Type, Function, Args) -> -@@ -3627,13 +3487,13 @@ +@@ -3633,13 +3493,13 @@ node_action(Host, Type, Function, Args) -> ?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]), @@ -677,7 +677,7 @@ case tree_call(Host, get_node, [Host, Node]) of N when is_record(N, pubsub_node) -> case Action(N) of -@@ -3646,8 +3506,14 @@ +@@ -3652,8 +3512,14 @@ end end, Trans). @@ -694,7 +694,7 @@ {result, Result} -> {result, Result}; {error, Error} -> {error, Error}; {atomic, {result, Result}} -> {result, Result}; -@@ -3655,6 +3521,15 @@ +@@ -3661,6 +3527,15 @@ {aborted, Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), {error, ?ERR_INTERNAL_SERVER_ERROR}; @@ -710,7 +710,7 @@ {'EXIT', Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), {error, ?ERR_INTERNAL_SERVER_ERROR}; -@@ -3663,6 +3538,17 @@ +@@ -3669,6 +3544,17 @@ {error, ?ERR_INTERNAL_SERVER_ERROR} end.