Software /
code /
prosody
Comparison
plugins/mod_pep.lua @ 10036:045209b41b3a 0.11
mod_pep: Handle presence based subscription outside of util.pubsub (fixes #1372)
Subscriptions were updated for each incoming presence stanza from
contacts. Each subscription change triggered a configuration save, which
would filter out the presence based subscriptions and usually end up
replacing the existing data with identical data. With many subscribed
nodes this adds up to a fair bit of IO bound work that is avoided by
keeping them separate.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 30 May 2019 15:16:56 +0200 |
parent | 9827:fd8aaab6669c |
child | 10037:e01f38acde74 |
child | 10045:6714578cfd6e |
comparison
equal
deleted
inserted
replaced
10029:2c8f674b9243 | 10036:045209b41b3a |
---|---|
88 }; | 88 }; |
89 end | 89 end |
90 return data, err; | 90 return data, err; |
91 end | 91 end |
92 function store:set(node, data) | 92 function store:set(node, data) |
93 if data then | |
94 -- Save the data without subscriptions | |
95 local subscribers = {}; | |
96 for jid, sub in pairs(data.subscribers) do | |
97 if type(sub) ~= "table" or not sub.presence then | |
98 subscribers[jid] = sub; | |
99 end | |
100 end | |
101 data = { | |
102 name = data.name; | |
103 config = data.config; | |
104 affiliations = data.affiliations; | |
105 subscribers = subscribers; | |
106 }; | |
107 end | |
108 return node_config:set(username, node, data); | 93 return node_config:set(username, node, data); |
109 end | 94 end |
110 function store:users() | 95 function store:users() |
111 return pairs(known_nodes:get(username) or {}); | 96 return pairs(known_nodes:get(username) or {}); |
112 end | 97 end |
149 item:maptags(function () return nil; end); | 134 item:maptags(function () return nil; end); |
150 end | 135 end |
151 end | 136 end |
152 message:add_child(item); | 137 message:add_child(item); |
153 end | 138 end |
139 | |
140 local broadcast_to = {}; | |
154 for jid in pairs(jids) do | 141 for jid in pairs(jids) do |
142 broadcast_to[jid] = true; | |
143 end | |
144 | |
145 local service_recipients = recipients[username]; | |
146 if service_recipients then | |
147 local service = services[username]; | |
148 for recipient, nodes in pairs(service_recipients) do | |
149 if nodes:contains(node) and service:may(node, recipient, "subscribe") then | |
150 broadcast_to[recipient] = true; | |
151 end | |
152 end | |
153 end | |
154 | |
155 for jid in pairs(broadcast_to) do | |
155 module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); | 156 module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); |
156 message.attr.to = jid; | 157 message.attr.to = jid; |
157 module:send(message); | 158 module:send(message); |
158 end | 159 end |
159 end | 160 end |
160 return simple_broadcast; | 161 return simple_broadcast; |
161 end | 162 end |
162 | 163 |
163 local function on_node_creation(event) | |
164 local service = event.service; | |
165 local node = event.node; | |
166 local username = service.config.pep_username; | |
167 | |
168 local service_recipients = recipients[username]; | |
169 if not service_recipients then return; end | |
170 | |
171 for recipient, nodes in pairs(service_recipients) do | |
172 if nodes:contains(node) then | |
173 service:add_subscription(node, recipient, recipient, { presence = true }); | |
174 end | |
175 end | |
176 end | |
177 | 164 |
178 function get_pep_service(username) | 165 function get_pep_service(username) |
179 module:log("debug", "get_pep_service(%q)", username); | 166 module:log("debug", "get_pep_service(%q)", username); |
180 local user_bare = jid_join(username, host); | 167 local user_bare = jid_join(username, host); |
181 local service = services[username]; | 168 local service = services[username]; |
231 services[username] = service; | 218 services[username] = service; |
232 module:add_item("pep-service", { service = service, jid = user_bare }); | 219 module:add_item("pep-service", { service = service, jid = user_bare }); |
233 return service; | 220 return service; |
234 end | 221 end |
235 | 222 |
236 module:hook("item-added/pep-service", function (event) | |
237 local service = event.item.service; | |
238 module:hook_object_event(service.events, "node-created", on_node_creation); | |
239 end); | |
240 | 223 |
241 function handle_pubsub_iq(event) | 224 function handle_pubsub_iq(event) |
242 local origin, stanza = event.origin, event.stanza; | 225 local origin, stanza = event.origin, event.stanza; |
243 local service_name = origin.username; | 226 local service_name = origin.username; |
244 if stanza.attr.to ~= nil then | 227 if stanza.attr.to ~= nil then |
301 if (current == empty_set or current:empty()) and (nodes == empty_set or nodes:empty()) then | 284 if (current == empty_set or current:empty()) and (nodes == empty_set or nodes:empty()) then |
302 return; | 285 return; |
303 end | 286 end |
304 | 287 |
305 local service = get_pep_service(service_name); | 288 local service = get_pep_service(service_name); |
306 for node in current - nodes do | |
307 service:remove_subscription(node, recipient, recipient); | |
308 end | |
309 | 289 |
310 for node in nodes - current do | 290 for node in nodes - current do |
311 if service:add_subscription(node, recipient, recipient, { presence = true }) then | 291 if service:may(node, recipient, "subscribe") then |
312 resend_last_item(recipient, node, service); | 292 resend_last_item(recipient, node, service); |
313 end | 293 end |
314 end | 294 end |
315 | 295 |
316 if nodes == empty_set or nodes:empty() then | 296 if nodes == empty_set or nodes:empty() then |